我有两个模型“ModelParent”和“ModelChild”,其中“ModelParent”有很多“ModelChild”,这是我的模型结构:
class ModelParent(models.Model):
... some params ...
class ModelChild(models.Model):
TYPES = (
(1, 'First'),
(2, 'Second'),
)
parent = models.ForeignKey(ModelParent, on_delete=models.CASCADE, related_name='childs')
type = models.SmallIntegerField(choices=TYPES, default=0)
目前,数据库中只有一个'ModelChild'属于当前数据库中唯一的'ModelParent','ModelChild'的'type'值等于'1',我得到' ModelParent' 对象,我需要将类型为“1”的“ child ”的数量以及类型为“2”的“ child ”的数量汇总到它,这就是我尝试这样做的方式:
queryset = ModelParent.objects \
.annotate(first_count=Count('childs', filter=Q(childs__type=1))) \
.annotate(second_count=Count('childs', filter=Q(childs__type=2))).get(pk=1)
查询没有抛出任何错误,但是在查看响应时,两个注释的值都是“1”,而“first_count”应该是“1”,“second_count”应该是“0”。
我还注意到,无论我在过滤器“filter=Q(childs__type=1)”中为“childs__type”设置什么值,结果始终相同,我可以这样设置,例如:“childs__type” =10' 并且计数仍然等于 '1'.. 就像整个 'filter' 参数都被忽略了。
请您参考如下方法:
基于 this answer我设法以这种方式实现了它,但我需要向子查询添加一些东西,例如“output_field”和注释的“Coalesce”,django 需要“output_field”,没有它就无法工作,并且“Coalesce' 是必需的,因为如果结果为零,默认情况下子查询将返回 'null',所以 'Coalesce' 所做的是在结果为 null 时检索默认值,在这种情况下我将其设置为零:
childs_base_query = ModelChild.objects.filter(parent=OuterRef('pk'))
first_type_query = Subquery(childs_base_query
.filter(type=1)
.values('parent')
.annotate(count=Count('pk'))
.values('count')
, output_field=IntegerField())
second_type_query = Subquery(childs_base_query
.filter(type=2)
.values('parent')
.annotate(count=Count('pk'))
.values('count')
, output_field=IntegerField())
queryset = ModelParent.objects \
.annotate(first_count=Coalesce(first_type_query, 0)) \
.annotate(second_count=Coalesce(second_type_query, 0))
我希望它能帮助到其他人。
