在 Django 中有效地获取相关模型的计数
Posted
技术标签:
【中文标题】在 Django 中有效地获取相关模型的计数【英文标题】:Get count of related model efficiently in Django 【发布时间】:2014-06-06 06:38:23 【问题描述】:我有这样的情况(实际代码绑定在模板中,为简洁起见省略)。
threads = Thread.objects.all()
for thread in threads:
print(thread.comments.count())
print(thread.upvotes.count())
我已经设法使用 Django 很棒的 prefetch_related
方法大大减少了查询的总数。
threads = Thread.objects.prefetch_related('comments').prefetch_related('upvotes')
但是我想知道这种情况是否可以进一步优化。据我了解prefetch_related
检索与相关模型关联的所有数据。鉴于我只关心相关模型的数量,而不关心模型本身,看来这个查询可以进一步优化,以便它不会检索到一堆不必要的数据。有没有办法在 Django 中做到这一点而不会下降到原始 SQL?
【问题讨论】:
【参考方案1】:您说得对,如果您只想获取计数,那么从数据库中获取所有数据是很浪费的。我建议注释:
threads = (Thread.objects.annotate(Count('comments', distinct=True))
.annotate(Count('upvotes', distinct=True)))
for thread in threads:
print(thread.comments__count)
print(thread.upvotes__count)
请参阅annotation documentation 了解更多信息。
【讨论】:
太棒了,这正是我想要的,谢谢!同样通过 Django 的文档搜索,看起来 1.7 将能够实现类似于我使用新的 Prefetch 类和延迟未使用字段的自定义查询集所描述的东西。但是,您的解决方案适用于 Django 的非前沿版本。 @rectangletangle:如果您只关心计数,注释应该仍然比prefetch_related
工作得更好。即使您推迟了除 id 之外的所有内容,当您可以为每个线程获取一个整数(计数)时,也没有理由为每个评论获取一个整数。
这很好。在这和兼容性之间,我认为你有这个用例的优越解决方案。
无论如何要获得自定义查询集的计数?就像只计算已发布的 cmets?
@CollinAnderson:抱歉,刚刚注意到您的评论。也许filter
参数是您正在寻找的?例如。 Count('comments', filter=Q(comments__is_published=True))
。 aggregation cheat sheet 上有几个例子。以上是关于在 Django 中有效地获取相关模型的计数的主要内容,如果未能解决你的问题,请参考以下文章
Django Query 获取 ArrayField 列的所有不同值的计数
在 Django 模板中获取 GAE 类 collection_name 的计数