Python 在Django中对相关对象进行迭代:循环查询集或使用一行选择相关(或预取相关)
我有一个新闻稿应用程序,其中一份新闻稿在每期中有多篇文章。我想在线显示一个摘要页面,列出时事通讯的年份、卷和标签,然后在无序列表中显示该期的所有文章。我对Django很陌生,所以我正在努力确定最好的方法 我已定义模型(仅相关部分):Python 在Django中对相关对象进行迭代:循环查询集或使用一行选择相关(或预取相关),python,django,orm,Python,Django,Orm,我有一个新闻稿应用程序,其中一份新闻稿在每期中有多篇文章。我想在线显示一个摘要页面,列出时事通讯的年份、卷和标签,然后在无序列表中显示该期的所有文章。我对Django很陌生,所以我正在努力确定最好的方法 我已定义模型(仅相关部分): Models.py: 班级时事通讯(models.Model): 音量=型号。外键(音量) 年份=型号。整型字段() 季节=型号.CharField(最大长度=6,选择数=数量/季节) label=models.CharField(最大长度=20) number=m
Models.py
:
班级时事通讯(models.Model):
音量=型号。外键(音量)
年份=型号。整型字段()
季节=型号.CharField(最大长度=6,选择数=数量/季节)
label=models.CharField(最大长度=20)
number=models.IntegerField()
类文章(models.Model):
时事通讯=型号。外键(时事通讯)
截面=模型。外键(截面)
title=models.CharField(最大长度=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>
然后使用以下模板进行渲染:
时事通讯\u list.html
:
{%block content%}
{新闻稿中的文章百分比,新闻稿列表中的文章百分比}
{{newsletter.label}
卷{{newsletter.Volume},编号{{newsletter.Number}
{{newsletter.article}
{%对于文章中的%a}
- {{a.title}}
{%endfor%}
{%endfor%}
{%endblock%}
非常简单,但由于我对Django还很陌生,我想知道我所做的工作是否完全没有效率,因为它强大的ORM。如果有更快的方法,我希望不必在运行中列出一个列表,然后将这两个列表一起列出
TIA。您现在所采用的方法将非常低效,因为它将导致1+N个查询。也就是说,1用于查询所有新闻稿,然后1用于每次评估这些
n.article\u set.all()
结果。因此,如果在第一个查询中有100个Newletter对象,那么将执行101个查询
这是使用prefetch\u 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 %}
{%block content%}
{时事通讯中的时事通讯%u列表%}
{{newsletter.label}
卷{{newsletter.Volume},编号{{newsletter.Number}
{{newsletter.article}
{newsletter.article_set.all%}
- {{a.title}}
{%endfor%}
{%endfor%}
{%endblock%}
太棒了!我以为我做这件事效率很低。我刚刚尝试了您的代码示例,不幸的是,newsletter.article\u set.all上的for循环没有返回任何内容?{%a在newsletter.articles\u set.all%}知道我做错了什么吗?谢谢你写了articles\u set.all
当它应该是article\u set.all
@tatlar时。有关更多信息,请参阅。道歉。非常感谢你们两位@jdi是否有类似的解决方案,如果我希望每个新闻稿都有最新的5篇文章?@Acute-使用模板标记{%作为新闻稿中的文章集。所有|切片:“5”%}将得到前五个结果。您需要确保已在视图中使用order_by对查询集进行了排序。