Django — Как запросить самые последние отдельные строки до даты вступления в силу?

#django #django-queryset

#джанго #django-набор запросов

Вопрос:

У меня есть модель, полная эффективных датированных ставок. Примечательными полями для этих ставок являются name , type , effective_date , и rate .

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

 ModifierRate.objects.filter(
                type=settings.MODIFIER_RATE_TYPES_TAX,
                effective_date__lte=date)
 

Этот запрос может возвращать одинаковые name значения, и type поэтому мне нужно, чтобы они были разными в этих двух полях.

 .distinct('name', 'type')`
 

Однако, если есть повторяющиеся имя и тип, мне нужен самый последний.

 .order_by('-effective_date')
 

После всего этого мне нужно суммировать ставки по этим объектам.

 .aggregate(rate__sum=Coalesce(Sum('rate'), 0))['rate_sum']
 

Если я попытаюсь разбить все эти вещи вместе, я получу

     raise NotImplementedError("aggregate()   distinct(fields) not implemented.")
NotImplementedError: aggregate()   distinct(fields) not implemented.
 

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

Как мне получить сумму ставок до определенной даты, которые различаются по имени и типу полей, где используется самая последняя отдельная ставка?

Спасибо.

Ответ №1:

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

 most_recent = ModifierRate.objects.filter(
    name=OuterRef('name'), 
).order_by(
    '-effective_date'
)

result = ModifierRate.objects.filter(
    type=settings.MODIFIER_RATE_TYPES_TAX,
    effective_date__lte=date
    pk=Subquery(most_recent.values('pk')[:1])
).aggragate(
    rate__sum=Coalesce(Sum('rate'), 0)
)['rate_sum']
 

Комментарии:

1. Я не думаю, что это удалит дубликаты по типу и имени, не так ли? И как мне убедиться, что удаляемые дубликаты являются более старыми?

2. Спасибо, я попробую и отчитаюсь