Запрос Django ORM дублирует аннотированные значения - PullRequest
0 голосов
/ 18 декабря 2018

У меня два почти одинаковых тестовых запроса:

test1 = (
Invoice.objects
    .filter(id=2787)
    .annotate(plan_total=Sum(
        'item_reason__planned_bank_operations__amount')
    ))

test2 = (
Invoice.objects
    .filter(id=2787)
    .annotate(
        plan_total=Sum(
            'item_reason__planned_bank_operations__amount'),
        pieces_total=Sum(
            'invoice_pieces__amount')
    ))

Результат test1.values('plan_total') возвращает <QuerySet [{'plan_total': Decimal('658.00')}]>, но когда я пытаюсь получить те же значения test2.values('plan_total'), он возвращает <QuerySet [{'plan_total': Decimal('1316.00')}]>.Как это могло произойти?

Немного больше информации о полях выше:

item_reason равно ForeignKey, когда planned_bank_operations - связанный запрос, связанный с related_name в PlanOperationмодель.

Та же история с invoice_pieces.InvoicePiece - это отдельная модель, у которой ForeignKey to Invoice со связанным именем InvoicePieces.

Итак, я не могу понять это поведение.Это ошибка или фича?

1 Ответ

0 голосов
/ 07 января 2019

После того, как я нашел примечание к статье https://docs.djangoproject.com/en/2.1/ref/models/querysets/#order-by, я предположил, что проблема в сгенерированном SQL с GROUP_BY.

Я решил эту проблему с помощью подзапроса:

test2_subquery = (
InvoiceAmountInProject.objects
    .filter(base_invoice__id=OuterRef('id'))
    .values('base_invoice__id')
    .annotate(total=Sum('amount'))
    .values('total'))

test2 = (
Invoice.objects
    .filter(id=2787)
    .annotate(
        plan_total=Sum('item_reason__planned_bank_operations__amount'),
        pieces_total=Subquery(test2_subquery)
    ))

Теперь test2.values('plan_total') возвращает правильное значение.

...