我有两个模型'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”的“孩子”的数量以及类型为“2”的“孩子”的数量汇总到它,这是我尝试这样做的方式:
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'。就像整个'过滤器'参数被忽略一样。
基于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))
我希望它可以帮助别人。