我有一个定义如下的方法:
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
答案 0 :(得分:0)
最小化查询数量的最佳方法是自己创建SQL语句,并使用SQLCommand和SQLDataAdapter以旧式方式执行它们。这样,您可以将所有数据堆叠到一个查询中,该查询返回可用于不同视图的多个表。
更好 - 创建一个将返回所有所需数据的存储过程。 SQL Server可以优化/保存存储过程的执行计划,使其更加高效。
如果你真的想坚持使用LINQ,那么不幸的是,这可能无济于事。