Iterating over related objects in Django: loop over query set or use one-liner select_related (or prefetch_related)

后端 未结 1 388
隐瞒了意图╮
隐瞒了意图╮ 2020-12-13 15:48

I have a newsletter application where a newsletter has multiple articles within each issue. I want to display a summary page online that lists the newsletter year, volume an

相关标签:
1条回答
  • 2020-12-13 16:52

    The approach you are doing now will be heavily inefficient, because it will result in an 1+N number of queries. That is, 1 for the query of all your Newsletters, and then 1 for every single time you evaluate those n.article_set.all() results. So if you have 100 Newletter objects in that first query, you will be doing 101 queries.

    This is an excellent reason to use prefetch_related. It will only result in 2 queries. One to get the Newsletters, and 1 to batch get the related Articles. Though you are still perfectly able to keep doing the zip to organize them, they will already be cached, so really you can just pass the query directly to the template and loop on that. :

    view

    newsletters = Newsletter.objects.prefetch_related('article_set').all()\
                        .order_by('-year', '-number')
    
    return render_to_response('newsletter/newsletter_list.html',
                              {'newsletter_list': newsletters})
    

    template

    {% block content %}
      {% for newsletter in newsletter_list %}
        <h2>{{ newsletter.label }}</h2>
        <p>Volume {{ newsletter.volume }}, Number {{ newsletter.number }}</p>
        <p>{{ newsletter.article }}</p>
        <ul>
        {% for a in newsletter.article_set.all %}
          <li>{{ a.title }}</li>
        {% endfor %}
        </ul>
      {% endfor %}
    {% endblock %}
    
    0 讨论(0)
提交回复
热议问题