django使用基于查询的聚合值来注释模型

时间:2017-09-15 17:56:46

标签: django django-models django-queryset django-aggregation django-annotate

假设我有以下模型结构:

Parent():

Child():
parent = ForeignKey(Parent)

GrandChild():
child = ForeignKey(Child)
state = BooleanField()
num = FloatField()

我正在尝试从父ViewSet恢复以下内容:

  1. 孩子的数量。
  2. 'state'为True时'num'字段的SUM。
  3. 我可以做以下事情:

    queryset = Parent.objects\
        .annotate(child_count=Count('child'))\
        .annotate(sum_total=Sum('child__grandchild__num'))
    

    这给了我(1)而不是(2)它给了我所有孙子的SUM。如何在确保所有Parent对象仍在QuerySet中的同时适当地过滤孙子?

3 个答案:

答案 0 :(得分:1)

尝试在注释

之前使用过滤器
queryset = Parent.objects.filter(child__grandchild__state=True')\
    .annotate(child_count=Count('child'))\
    .annotate(sum_total=Sum('child__grandchild__num'))

答案 1 :(得分:0)

您使用的是哪个版本的django?如果支持版本,也可以使用子查询。

Parent.objects
.annotate(child_count=Count('child'))
.annotate(
    grandchild_count_for_state_true=Subquery(
        GrandChild.objects.filter(
            state=True,
            child=OuterRef('pk')
        ).values('parent')
        .annotate(cnt=Sum('child__grandchild__num'))
        .values('cnt'),
        num=models.IntegerField()
    )
)

您可以通过聚合查询对此进行优化。

答案 2 :(得分:0)

您可以执行以下操作:

qs = Parents.objects.all()
child_count = Count('children')
num_sum = Sum('children__grandchildren__num', filter=Q(children__grandchildren__state=True))
qs = qs.annotate(child_count=child_count).annotate(num_sum=num_sum)

孩子和孙子是您可以在模型中定义的相关名称