Django Count过滤注释不起作用

时间:2017-12-19 00:13:35

标签: python django django-models

我有两个型号' 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'的价值等于' 1',我得到了' ModelParent'对象和我需要汇总他的孩子的数量'类型是' 1'以及他的孩子的数量'其中type是' 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'当它应该是' 1'仅适用于' first_count'和' 0' for' second_count'。

我也注意到,无论我设定的是什么价值,所以' childs__type'在过滤器" filter = Q(childs__type = 1)"中,结果总是相同的,我可以这样设置它,例如:' childs__type = 10'并且计数仍等于' 1' ...就像整个'过滤器' param被忽略了。

1 个答案:

答案 0 :(得分:2)

基于this answer我设法以这种方式实现了它,但我需要添加一些内容,例如' output_field'到子查询和' Coalesce'对于注释,< output_field' django要求它,没有它就没有工作,并且' 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))

我希望它可以帮助别人。