ニュースレターの各号内に複数の記事があるニュースレターアプリケーションがあります。ニュースレターの年、巻、ラベルを一覧表示する概要ページをオンラインで表示し、その後、順不同リストに問題のすべての記事を表示したいと思います。私はDjangoにかなり慣れているので、これを行うための最良の方法を決定しようとしています。
モデルを定義しました(関連する部分のみ):
_Models.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()
である2つのリストと、テンプレートで反復select_related()
クエリセットを使用するprefetch_related()
クエリセットを使用する私は最初のオプションを使用してそれを働いています:
_Views.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})
_
次に、次のテンプレートを使用してレンダリングします。
_Newsletter_list.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 %}
_
かなり単純明快ですが、Django=に慣れていないので、私がしていることはその強力なORMに関して完全に非効率的であるのではないかと思っていました。より高速な方法がある場合は、2つのリストを一緒に飛ばしてZip()
を一緒に実行します。
TIA。
現在実行しているアプローチはheavly非効率になります。これは1 + Nのクエリ数になるためです。つまり、すべてのニュースレターのクエリに1つ、次にn.article_set.all()
の結果を評価するたびに1つになります。したがって、最初のクエリに100個のNewletterオブジェクトがある場合、101個のクエリを実行します。
これがprefetch_related
を使用する優れた理由です。結果は2つのクエリのみになります。 1つはニュースレターを取得するため、もう1つは関連する記事をバッチで取得するためのものです。 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 %}