Python 在Django中,有没有一种方法可以通过相关对象上的条件聚合关系

Python 在Django中,有没有一种方法可以通过相关对象上的条件聚合关系,python,sql,django,django-queryset,Python,Sql,Django,Django Queryset,Django aggregation文档给出了一个示例,该示例统计与每个出版商相关的图书的数量,并返回一个查询集,其中前5位出版商用他们的图书计数进行了注释(如用此计数附加一个新字段): 但我只需要计算一种特定类型的书。差不多 >>> pubs = Publisher.objects.annotate(num_books=Count('book__type="nonfiction"')).order_by('-num_books')[:5] 是否有一个过滤器可以用来实现这一点

Django aggregation文档给出了一个示例,该示例统计与每个
出版商相关的
图书
的数量,并返回一个查询集,其中前5位出版商用他们的图书计数进行了注释(如用此计数附加一个新字段):

但我只需要计算一种特定类型的书。差不多

>>> pubs = Publisher.objects.annotate(num_books=Count('book__type="nonfiction"')).order_by('-num_books')[:5]
是否有一个过滤器可以用来实现这一点,或者我需要求助于原始SQL

以上是与我的实际问题类似的docs示例,即当系统和医院都被建模为医疗保健
实体时,通过系统中的医院数量识别和量化最大的医疗集团:

>>> biggest_systems = Entity.objects.filter(relationships__type_id=NAME_TO_TYPE_ID.get('hospital')).annotate(num_hospitals=Count('relationships')).order_by('-num_hospitals')[:5]
>>> biggest_systems[0].num_hospitals
25
关系
是一个实体M2M字段,带有一个直通表,type_id也是实体内的一个字段:

class Entity(models.Model):
    id = models.AutoField(verbose_name='ID',primary_key=True, db_column='ID') 
    type_id = models.IntegerField(verbose_name='detailed type',db_column='TypeID', blank=True, editable=True, choices=ENTITYTYPE_CHOICES, help_text="A category for this healthcare entity.")
    relationships = models.ManyToManyField('self', verbose_name='affiliated with', through='EntityRelationship', symmetrical=False, related_name='related_to+')
见:

或者在您的情况下:

Publisher.objects.filter(book__type='nonfiction').annotate(num_books=Count('book'))

哇!能这么简单吗?现在检查一下。是的,我也被打动了,首先我想这会过滤出版商,至少有一本“非小说类”的书。所以我试过了(是的,我真的试过了,我想至少我想出了一些ORM巫毒术…)并且它确实过滤了注释的书籍类型。。。很好的问题,很好地知道,对问题B)我的num_books在所有通过过滤器的情况下都等于1,但我的“真实”示例有点复杂——通过
通过
(关系中介)表中的字段(属性)自引用M2M。我不想接受你的答案,直到我(通过尝试docs的例子)确信没有什么巫术不能产生我们期望的效果。你能发布你的实际模型和一些数据吗?(./manage.py dumpdata yourapp.yourmodel1 yourapp.yourmodel2等…)谢谢!威尔科。刚刚检查过,你是对的,它工作得很完美,甚至从我更复杂的例子。如果我能加倍投票,我会的。我最初的错误是将列表中的前几个出版商按递增而不是递减的顺序排序。我在寻找最大的非小说类出版商,而不是最小的(根据docs的例子)。我将发布我的真实例子,根据系统中医院的数量寻找最大的医疗集团。
Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book'))
Publisher.objects.filter(book__type='nonfiction').annotate(num_books=Count('book'))