我有一个方法定义如下:
def get_featured_books(cats=0):
"""
This method would return a list of featured books
"""
fbooks = list()
categories = models.Category.objects.annotate( bookcount=Count('book')).order_by('bookcount')[:cats].reverse()
for item in categories:
fbooks.append(item.book_set.latest('posted_date'))
return fbooks
我在主页视图上使用上述方法显示精选书籍列表。在模板中,我使用以下标签:
{% for book in featured %}
<h2>{{ book.title }}({{ book.category}})</h2>
<span class="authors">{{book.authors.all|join:','}}</span>
{% endfor %}
但是这整个概念提出了很多疑问。例如,如果我想展示 10 本特色书籍:
categories = models.Category.objects.annotate( bookcount=Count('book')).order_by('bookcount')[:cats].reverse()
将进行一次查询。
for item in categories:
fbooks.append(item.book_set.latest('posted_date'))
将进行 10 次查询。
在模板中{{ book.category}}
,{{ book.authors.all }}
每本书都会进行 1 次查询,因此在我的场景中,上述两个标签将进行 20 次查询。这使得它总共有 30 个查询(只是为了显示 10 条记录的列表)。当然,我将在主页上显示其他内容,这些内容将进行额外的查询。
问题是我怎样才能减少(最低)否。查询以获取上述信息。通常的做法是什么?
(PS:我知道缓存,我知道信息可以被缓存,但我在这里的目的是学习如何进行有效的查询。)
更新:
正如KrzysiekSzularz建议的那样,我尝试使用select_related
和prefetch_related
如下,但 django 调试工具栏仍然显示它进行 32 个查询。
def get_featured_books(cats=0):
"""
This method would return a list of featured books
"""
fbooks = list()
categories = models.Category.objects.select_related().annotate( bookcount=Count('book')).order_by('bookcount')[:cats].reverse()
for item in categories:
fbooks.append(item.book_set.prefetch_related('category').latest('posted_date'))
return fbooks