Получение суммарной суммы из агрегированного поля с помощью Django orm

В моем проекте я хочу получить сумму поля "amount", которое формирует агрегат. Я прочитал несколько постов об этом, но не могу найти способ достичь того, что я хочу.

Пример модели:

class ScheduledOperation:
   day = models.dateField()
   amount = models.DecimalField(...)

Пример кверисета

{'day': datetime.date(2023, 2, 7), 'amount': Decimal('-500.00')} # same day each month
{'day': datetime.date(2023, 2, 7), 'amount': Decimal('1500.00')} # same day each month

{'day': datetime.date(2023, 3, 7), 'amount': Decimal('-500.00')}
{'day': datetime.date(2023, 3, 7), 'amount': Decimal('1500.00')}

{'day': datetime.date(2023, 4, 7), 'amount': Decimal('-500.00')}
{'day': datetime.date(2023, 4, 7), 'amount': Decimal('1500.00')}

{'day': datetime.date(2023, 5, 7), 'amount': Decimal('-500.00')}
{'day': datetime.date(2023, 5, 7), 'amount': Decimal('1500.00')}

{'day': datetime.date(2023, 5, 8), 'amount': Decimal('-4000.00')} # big op here

Где я нахожусь на данный момент

ScheduledOperation.objects.order_by('day').values('day').annotate(day_tot=Sum('amount')) дает мне общую сумму за каждый день:

{'day': datetime.date(2023, 2, 7), 'day_tot': Decimal('1000')}
{'day': datetime.date(2023, 3, 7), 'day_tot': Decimal('1000')}
{'day': datetime.date(2023, 4, 7), 'day_tot': Decimal('1000')}
{'day': datetime.date(2023, 5, 7), 'day_tot': Decimal('1000')}
{'day': datetime.date(2023, 5, 8), 'day_tot': Decimal('-4000')}

Что я хочу

{'day': datetime.date(2023, 2, 7), 'day_tot': Decimal('1000'), 'cumul_amount':Decimal('1000')}
{'day': datetime.date(2023, 3, 7), 'day_tot': Decimal('1000'), 'cumul_amount':Decimal('2000')}
{'day': datetime.date(2023, 4, 7), 'day_tot': Decimal('1000'), 'cumul_amount':Decimal('3000')}
{'day': datetime.date(2023, 5, 7), 'day_tot': Decimal('1000'), 'cumul_amount':Decimal('4000')}
{'day': datetime.date(2023, 5, 8), 'day_tot': Decimal('-4000'), 'cumul_amount':Decimal('0')}

Что я пробовал

После прочтения других сообщений на эту тему, я попытался использовать функцию Window:

self.coming_scheduled_ops.order_by('day').values('day').annotate(
    day_tot=Sum('amount')
).annotate(
    cumul_amount=Window(
        Sum('amount'),order_by='day'
    )
) 

но это не работает:

{'day': datetime.date(2023, 2, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('1500')}
{'day': datetime.date(2023, 3, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('3000')}
{'day': datetime.date(2023, 4, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('4500')}
{'day': datetime.date(2023, 5, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('6000')}
{'day': datetime.date(2023, 5, 8), 'day_tot': Decimal('-4000'), 'cumul_amount': Decimal('2000')}

Я не могу использовать Window(Sum('day_tot')), он выбрасывает django.core.exceptions.FieldError: Cannot compute Sum('day_tot'): 'day_tot' is an aggregate

Мог бы кто-нибудь помочь мне понять функцию Window plz?

Я не уверен, что это возможно с помощью Django ORM, но вы можете легко сделать это с помощью Python.

queryset = ScheduledOperation.objects.all()
queryset = (
    queryset.order_by('day')
    .values('day')
    .annotate(day_tot=Sum('amount'))
)
cumul_amount = 0
for day in queryset:
    cumul_amount += day['day_tot']
    day['cumul_amount'] = cumul_amount

В результате получается:

{'day': datetime.date(2023, 2, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('1000')}
{'day': datetime.date(2023, 3, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('2000')}
{'day': datetime.date(2023, 4, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('3000')}
{'day': datetime.date(2023, 5, 7), 'day_tot': Decimal('1000'), 'cumul_amount': Decimal('4000')}
{'day': datetime.date(2023, 5, 8), 'day_tot': Decimal('-4000'), 'cumul_amount': Decimal('0')}
Вернуться на верх