Django GenerateSeries возвращает один и тот же ряд несколько раз
У меня есть модель встречи с starts_at, repeat_duration
Я хочу аннотировать повторяющиеся значения, возвращаемые из сгенерированной серии, полем длительности суммы до даты окончания
так, если дата записи на прием 14-07-2024, дата окончания 25-07-2024 и продолжительность 3 дня он возвращает 14, 17, 20, 23 в виде массива аннотация
но я получаю один и тот же объект, возвращаемый несколько раз, и каждый раз он имеет одно значение из серии result
для примера будет возвращено четыре раза по одному для каждого значения и repeat_days будет этим значением
object_1.repeat_days = 14 object_2.repeat_days = 17
как сделать так, чтобы он возвращал только один объект и значения в виде массива
пробовал обернуть GenerateSeries в arrayagg, но получаю
Вызовы агрегатных функций не могут содержать вызовы функций с возвратом набора
class AppointmentQuerySet(models.QuerySet):
def annotate_repeated_days(self, end_date):
return self.annotate(
repeat_dates=ArrayAgg(
GenerateSeries(
models.F("starts_at"), models.F("repeat_duration"), end_date
)
)
)
функция:
from django.db import models
class GenerateSeries(models.Func):
function = 'generate_series'
output_field = models.DateTimeField()
def __init__(self, start, step, stop, **extra):
expressions = [
start,
stop,
step
]
super().__init__(*expressions, **extra)
Есть идеи?
Это приводит к недопустимой конструкции SRF-in-aggregate, на которую указывает ошибка
array_agg(generate_series(starts_at,end_date,repeat_duration)) as repeat_dates
Но это ограничение легко обойти, переместив функцию возврата набора в подзапрос и позволив агрегатной функции извлекать строки из него:
(select array_agg(n) as repeat_dates
from(select generate_series(starts_at,end_date,repeat_duration)) as g(n))
Вы можете заставить Django использовать синтаксис подзапроса, установив subquery=True
:
from django.db import models
class GenerateSeries(models.Func):
subquery = True ###################### here
function = 'generate_series'
output_field = models.DateTimeField()
def __init__(self, start, step, stop, **extra):
expressions = [#side-note: why reorder Postgres' (stOp,stEp) to (stEp,stOp)?
start,
stop,
step
]
super().__init__(*expressions, **extra)
Django проверяет, что здесь и это влияет на решение здесь:
# Decide if we need to use a subquery. # # Existing aggregations would cause incorrect results as # get_aggregation() must produce just one result and thus must not use # GROUP BY. # # If the query has limit or distinct, or uses set operations, then # those operations must be done in a subquery so that the query # aggregates on the limit and/or distinct results instead of applying # the distinct and limit after the aggregation.