Запрос для перебора записей по дате в django

Я пытаюсь найти лучший способ циклического просмотра заказов на следующие семь дней, включая сегодняшний, что у меня уже есть:

unfilled_orders_0 = Model.objects.filter(delivery_on__date=timezone.now() + timezone.timedelta(0))
context['todays_orders'] = unfilld_orders_0.aggregate(field_1_sum=Sum('field_1'), field_2_sum=Sum('field_2'),field_3_sum=Sum('field_3'), field_4_sum=Sum('field_4'),field_5_sum=Sum('field_5'))

Мне интересно, могу ли я как-то избежать необходимости делать это семь раз - по одному на каждый день. Я предполагаю, что есть более эффективный способ сделать это.

Вы можете сделать это с помощью цикла for и сохранить данные в контексте, как показано ниже

from django.utils import timezone
from django.db.models import Sum
context = {}
for i in range(7):
    qs = Model.objects.filter(delivery_on__date=(timezone.now() + timezone.timedelta(i)).date())
    context = {}
    context[f'orders_{i}'] = qs.aggregate(
        field_1_sum=Sum('field_1'),
        field_2_sum=Sum('field_2'),
        field_3_sum=Sum('field_3'),
        field_4_sum=Sum('field_4'),
        field_5_sum=Sum('field_5'))

Этот запрос ударит по базе данных 7 раз, в противном случае вы можете использовать другой подход, который ударит по базе данных только один раз

context = {}
qs = Model.objects.filter(delivery_on__date__lte=timezone.now()-timezone.timedelta(days=7)).order_by('delivery_on')
dates = qs.values('delivery_on__date', flat=True).distinct()
for i in dates:
    _qs = qs.filter(create_ts__date=i)
    context[f'orders_{i}'] = _qs.aggregate(
        field_1_sum=Sum('field_1'),
        field_2_sum=Sum('field_2'),
        field_3_sum=Sum('field_3'),
        field_4_sum=Sum('field_4'),
        field_5_sum=Sum('field_5'))

Вы определяете, на сколько дней назад qs будет включать все заказы, затем distinct указываете даты и фильтруете уже отфильтрованные qs по датам.

Вы можете сделать это с помощью одного запроса ORM / db, предоставив Sum дополнительный аргумент filter:

days_ahead = 7
fields = ["field_1", "field_2", ...]
aggregate_kwargs = {
    s_{field}_{day}=Sum(field, filter=Q(now+timedelta(days=day)))
    for field in fields
    for day in range(days_ahead)
}
unfilled_orders = Model.objects.filter(delivery_on__date__lt=now+timedelta(days=days_ahead)
context.update(unfilled_orders.aggregate(**aggregate_kwargs))
Вернуться на верх