Аннотируйте QuerySet с максимальным полем даты и датой, созданной вручную

У меня следующая модель:

class Item(models.Model):
    last_used = models.DateTimeField()
    created_at = models.DateTimeField()

Сейчас я пытаюсь посмотреть среднее "время жизни" предметов в месяц. Время жизни - это сколько дней в среднем используются предметы. Я могу рассчитать общее среднее значение следующим образом:

from django.db.models import IntegerField, F, Avg
from django.db.models.functions import Cast, ExtractDay, TruncDate

items = Item.objects.annotate(days_used=Cast(ExtractDay(TruncDate(F('last_used')) - TruncDate(F('created_at'))), IntegerField())+1)
avg = items.aggregate(Avg('days_used'))['days_used__avg']

Теперь, когда я хочу вычислить это значение за месяц, я хотел бы аннотировать запрос новым полем, которое является максимальным из created_at или начала рассматриваемого месяца. Это нужно для того, чтобы максимальное значение времени жизни для всех месяцев было равно количеству дней в этом месяце

Есть функция Greatest, которая, как мне кажется, может быть использована для этого, но я не уверен как. Если предположить, что нас интересует декабрь 2021 года, вот что у меня есть на данный момент:

from django.db.models.functions import Greatest
target_month = 12
items = items.annotate(created_max=Greatest(TruncDate(F('created_at')), TruncDate(F(timezone.datetime(2021, target_month, 1)))

Но использование timezone.datetime приводит к ошибке:

AttributeError: объект 'datetime.datetime' не имеет атрибута 'split'

ПРИМЕЧАНИЕ: Я знаю, что last_used может привести к превышению количества дней, но это другой вопрос, который мы решаем.

Вам следует использовать выражение django.db.models.Value вместо django.db.models.F для постоянных значений.

from django.db.models.functions import Greatest
target_month = 12
items = items.annotate(created_max=Greatest(TruncDate(F('created_at')), TruncDate(Value(timezone.datetime(2021, target_month, 1)))
Вернуться на верх