在Django中有效地获取相关模型的数量

rec*_*gle 13 python django django-orm django-queryset

我遇到类似这样的情况(实际代码绑定在模板中,为简洁起见省略).

threads = Thread.objects.all()
for thread in threads:
    print(thread.comments.count())
    print(thread.upvotes.count())
Run Code Online (Sandbox Code Playgroud)

我已经设法使用Django的真棒prefetch_related方法大大减少了查询总数.

threads = Thread.objects.prefetch_related('comments').prefetch_related('upvotes')
Run Code Online (Sandbox Code Playgroud)

但是我想知道这种情况是否可以进一步优化.据我所知,prefetch_related检索与相关模型相关的所有数据.看起来我只关心相关模型的数量,而不关心模型本身,似乎这个查询可以进一步优化,以便它不会检索一堆不必要的数据.有没有办法在Django中执行此操作而不降低到原始SQL?

Kev*_*nry 16

你是对的,如果要做的就是获取计数,从数据库中获取所有数据是浪费的.我建议注释:

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)
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅注释文档.

  • @rectangletangle:如果你关心的只是计数,那么注释应该比`prefetch_related`更好.即使你推迟了除id之外的所有东西,当你可以为每个线程获取一个整数(计数)时,没有理由为每个注释获取一个整数. (4认同)
  • @CollinAnderson:对不起,刚刚注意到你的评论.也许`filter`参数是你想要的?例如`Count('comments',filter = Q(comments__is_published = True))`.[聚合备忘单]上有几个例子(https://docs.djangoproject.com/en/dev/topics/db/aggregation/#cheat-sheet). (3认同)