我有一个新闻通讯应用程序,其中每期新闻通讯包含多篇文章。我想在线显示一个摘要页面,其中列出了新闻通讯的年份、卷数和标签,然后在
我有一个新闻通讯应用程序,其中每期新闻通讯包含多篇文章。我想在线显示一个摘要页面,其中列出新闻通讯的年份、卷数和标签,然后以无序列表的形式显示该期的所有文章。我对 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+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 %}