【问题标题】:Django Count filter annotation not workingDjango Count过滤器注释不起作用
【发布时间】:2018-06-01 09:01:57
【问题描述】:

我有两个模型“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' 的他的 'childs' 的计数以及类型为 '2' 的他的 'childs' 的计数聚合到它,这就是我试图这样做的方式:

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' 参数被忽略了。

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    基于this answer,我设法以这种方式实现了它,但我需要在子查询中添加一些东西,例如为子查询添加一些东西,并为注释添加一些东西,'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))
    

    我希望它可以帮助别人。

    【讨论】:

      猜你喜欢
      • 2016-01-10
      • 2015-04-07
      • 2012-09-19
      • 2016-10-08
      • 2012-03-07
      • 2018-02-09
      • 2012-04-05
      • 2019-08-17
      • 1970-01-01
      相关资源
      最近更新 更多