如何计算基于另一个查询集的多对多相关对象的计数?

How to calculate count of related many to many objects based on another queryset?

class Zone(Model):
  ...

class Flight(Model):
  zones = ManyToManyField(Zone)

flights = Flight.objects.filter(...)
qs1 = Zone.objects.annotate(
   count=flights.filter(zones__pk=F('pk')).distinct().count(),  # this is not valid expression
)

尽管查询集内有 F,注释中有 count(),但它仍然会抛出错误 TypeError: QuerySet.annotate() received non-expression(s): 0.,这意味着该查询集已就地执行。

也不起作用,但这次它只是 returns 无效值(总是 1,总是计算区域单个对象而不是过滤器内部的对象):

qs1 = Zone.objects.annotate(
   count=Count('pk', filter=flights.filter(zones__pk=F('pk'))),  # with 'flight' instead of first 'pk' it also doesn't work
)

A .count() 在 Django 中被 eagerly 求值,所以 Django 会尝试求值 flights.filter(zones__pk=F('pk')).distinct().count(),并且会成功,因为 F('pk') 将计算 fligts 的数量,其中 zones 恰好与 Flight 的主键具有相同的主键。您将需要在子查询上使用 OuterRef [Django-doc].annotate(..)

但是你把它搞得太复杂了。您可以简单地注释为:

from django.db.models import Q, Sum

Zone.objects.annotate(
    <b>count=Count('flight', distinct=True, filter=Q(flight__…))</b>
)

这里的 filter=Q(flight__…) 是您的航班过滤器的一部分。因此,如果 Flight 被假设的 active=True 过滤,您可以使用:

进行过滤
Zone.objects.annotate(
    count=Count('flight', distinct=True, filter=<b>Q(flight__active=True)</b>)
)