8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

在 Django 中迭代相关对象:循环查询集或使用单行 select_related (或 prefetch_related)

ATK 2月前

26 0

我有一个新闻通讯应用程序,其中每期新闻通讯包含多篇文章。我想在线显示一个摘要页面,其中列出了新闻通讯的年份、卷数和标签,然后在

我有一个新闻通讯应用程序,其中每期新闻通讯包含多篇文章。我想在线显示一个摘要页面,其中列出新闻通讯的年份、卷数和标签,然后以无序列表的形式显示该期的所有文章。我对 Django 还很陌生,所以我正在尝试确定实现此目的的最佳方法。

我已经定义了模型(仅相关部分):

模型.py:

class Newsletter(models.Model):
    volume = models.ForeignKey(Volume)
    year   = models.IntegerField()
    season = models.CharField(max_length=6, choices=VOLUME_SEASON)
    label  = models.CharField(max_length=20)
    number = models.IntegerField()

class Article(models.Model):
    newsletter = models.ForeignKey(Newsletter)
    section    = models.ForeignKey(Section)
    title      = models.CharField(max_length=200)

我希望在网络上看到的内容如下:

<h2>Spring 2012</h2>
<p>Volume 14, Number 1</p>
<ul>
    <li>Foo</li>
    <li>Bar</li>
    <li>Baz</li>
</ul>

<h2>Winter 2011</h2>
<p>Volume 13, Number 4</p>
<ul>
  <li>Boffo</li>
</ul>

非常简单。但是,我不知道该如何最好地编写我的视图。是否使用:

  • 在模板中迭代 zip() 两个列表
  • 使用 select_related() 查询集
  • 使用 prefetch_related() 查询集

我使用第一个选项来工作:

视图.py:

from django.shortcuts import render_to_response, get_object_or_404
from www.apps.newsletter.models import Newsletter, Article

def index(request):
    article_group = []
    newsletter = Newsletter.objects.all().order_by('-year', '-number')
    for n in newsletter:
        article_group.append(n.article_set.all())
    articles_per_newsletter = zip(newsletter, article_group)

    return render_to_response('newsletter/newsletter_list.html',
                              {'newsletter_list': articles_per_newsletter})

然后使用以下模板进行渲染:

新闻通讯_列表.html:

{% block content %}
  {% for newsletter, articles in newsletter_list %}
    <h2>{{ newsletter.label }}</h2>
    <p>Volume {{ newsletter.volume }}, Number {{ newsletter.number }}</p>
    <p>{{ newsletter.article }}</p>
    <ul>
    {% for a in articles %}
      <li>{{ a.title }}</li>
    {% endfor %}
    </ul>
  {% endfor %}
{% endblock %}

如果有更快的方法, zip() 我很乐意不必即时创建一个列表,然后将

爱。

帖子版权声明 1、本帖标题:在 Django 中迭代相关对象:循环查询集或使用单行 select_related (或 prefetch_related)
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由ATK在本站《django》版块原创发布, 转载请注明出处!
最新回复 (0)
  • Thom 2月前 0 只看Ta
    引用 2

    您现在采用的方法 极低 ,因为它将导致 1+N 次查询。也就是说,查询所有新闻通讯需要 1 次,然后每次评估这些 n.article_set.all() 结果时都需要 1 次。因此,如果您在第一个查询中有 100 个新闻通讯对象,那么您将执行 101 次查询。

    这是使用 的一个很好的理由 prefetch_related 。它只会导致 2 个查询。一个用于获取新闻通讯,另一个用于批量获取相关文章。虽然您仍然可以继续执行 来 zip 组织它们,但它们已经被缓存,因此您实际上可以将查询直接传递给模板并循环执行。:

    看法

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

    模板

    {% 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 %}
    
  • 太棒了!我以为我的方法效率不高。我刚刚尝试了您的代码示例,但不幸的是,newsletter.article_set.all 上的 for 循环没有返回任何内容?{% for a in newsletter.articles_set.all %} 知道我做错了什么吗?谢谢!

  • 您写成了 articles_set.all,但实际应该是 article_set.all @tatlar。请参阅以下关系以获取更多信息。

  • @Acute - 使用切片模板标签 {% for a in newsletter.article_set.all|slice:\'5\' %} 将获得前五个结果。您需要确保已使用视图中的 order_by 对查询集进行排序。

返回
作者最近主题: