Django аннотируют модели с совокупным значением на основе запроса
Допустим, у меня есть следующая структура модели:
Parent():
Child():
parent = ForeignKey(Parent)
GrandChild():
child = ForeignKey(Child)
state = BooleanField()
num = FloatField()
Я пытаюсь от родителя ViewSet
, восстановите следующее:
- Количество детей.
- Сумма полей 'num', когда 'state' - True.
Я могу сделать следующее:
queryset = Parent.objects\
.annotate(child_count=Count('child'))\
.annotate(sum_total=Sum('child__grandchild__num'))
Это дает мне (1), но вместо (2) это дает мне СУММУ для ВСЕХ внуков. Как я могу отфильтровать внуков должным образом, при этом у меня есть все Parent
объекты еще в QuerySet?
3 ответа
Какую версию 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()
)
)
Вы можете оптимизировать это с помощью запроса агрегации.
Попробуйте использовать фильтр до аннотации
queryset = Parent.objects.filter(child__grandchild__state=True')\
.annotate(child_count=Count('child'))\
.annotate(sum_total=Sum('child__grandchild__num'))
Вы можете сделать следующее:
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)
дети и внуки - это связанные имена, которые вы можете определить в своих моделях