Django - Аннотирование нескольких объектов Sum () дает неверный результат - PullRequest
3 голосов
/ 11 марта 2020

models.py выглядит следующим образом

class Channel(Model):
    name = CharField()

class Contract(Model):
    channel = ForeignKey(Channel, related_name='contracts')
    fee = IntegerField()

class ContractPayment(Model):
    contract = ForeignKey(Contract, related_name='payments')
    value = IntegerField()

Когда я запрашиваю модель:

Channel.objects.annotate(pay=Sum('contracts__fee'))

Возвращает: 75000 . И это правильно, но когда я запрашиваю, как это:

Channel.objects.annotate(pay=Sum('contracts__fee'))
               .annotate(paid=Sum('contracts__payments__value'))


И он возвращает: оплата: 96000, выплата: 33000 . Как видите, оплата изменена. Что здесь происходит? Я прочитал билет # 10060 но не повезло.

Ответы [ 3 ]

0 голосов
/ 11 марта 2020

Я думаю, вы должны использовать distinct=True в annotate(), как показано ниже ...

Channel.objects.annotate(pay=Sum('contracts__fee', distinct=True)).annotate(paid=Sum('contracts__payments__value', distinct=True))
0 голосов
/ 11 марта 2020

Если вы не используете Django3, я думаю, это должно работать:

from django.db.models import Subquery, OuterRef, Sum
contracts = Contract.objects.filter(channel__id=OuterRef("id")).values("fee")
tot = contracts.values("channel_id").annotate(total=Sum("fee")).values("total")
Channel.objects.annotate(pay=Subquery(tot), paid=Sum('contracts__payments__value')).values()
0 голосов
/ 11 марта 2020

Используйте два запроса для получения желаемого результата:

Channel.objects.annotate(pay=Sum('contracts__fee'))

и

Channel.objects.annotate(paid=Sum('contracts__payments__value'))
...