Django аннотация, приводящая к декартовому произведению - PullRequest
1 голос
/ 12 января 2020

У меня есть модель, в которой определенный класс будет иметь несколько дочерних классов. Пример дизайна:

class ParentModel(models.Model):
   ParentName = CharField(max_length=50)

class ChildModelA(models.Model):
   FK1 = ForeignKey(ParentModel, on_delete=models.CASCADE)
   ChildAValue = IntegerField(default=0)

class ChildModelB(models.Model):
   FK2 = ForeignKey(ParentModel, on_delete=models.CASCADE)
   ChildBValue = IntegerField(default=0) 

Что я пытаюсь сделать, так это суммировать по ParentName сумму всех ChildAValue и ChildBValue. Проблема, с которой я сталкиваюсь, заключается в том, что когда я выполняю оба запроса в одном запросе, я получаю декартово произведение между ChildA и ChildB. Пример запроса:

ParentModel.objects.all().values('ParentName').annotate(
   ChildASum = Sum('childamodel__ChildAValue),
   ChildBSum = Sum('childbmodel__ChildBValue),
)

Результирующий набор запросов дает мне сумму умножения ChildBValue, умноженную на общее количество объектов ChildA в FK ... означая, что 6 объектов ChildA, указывающих на этого конкретного Parent, умножат мое значение ChildB на 6. И наоборот для ChildASum.

Существуют ли способы объединения нескольких дочерних моделей одного и того же родителя без множественного объединения?

Спасибо!

1 Ответ

1 голос
/ 12 января 2020

Да, вам, вероятно, нужно работать с подзапросами здесь:

from django.db.models import OuterRef, Subquery, Sum

ParentModel.objects.values('ParentName').annotate(
    ChildASum=Subquery(
        ChildModelA.objects.filter(
           FK1=OuterRef('pk')
        ).annotate(
            total=Sum('ChildAValue')
        ).values('total').order_by('FK1')
   ),
   ChildBSum=Subquery(
        ChildModelB.objects.filter(
           FK2=OuterRef('pk')
        ).annotate(
            total=Sum('ChildAValue')
        ).values('total').order_by('FK1')
   )
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...