1

我有一个方法定义如下:

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_relatedprefetch_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
4

1 回答 1

0

尽量减少查询数量的最佳方法是自己创建 SQL 语句并使用 SQLCommand 和 SQLDataAdapter 以老式方式执行它们。这样,您可以将所有数据堆叠到一个查询中,该查询返回多个可用于不同视图的表。

更好的是 - 创建一个将返回所有需要的数据的存储过程。SQL Server 可以优化/保存存储过程的执行计划,使其更加高效。

如果您真的想坚持使用 LINQ,那么不幸的是,这可能无济于事。

于 2013-02-04T07:21:52.220 回答