Django подсчитывает условно аннотированные значения в операторе "group-by"

Имеет следующие модели:

class TheModel(models.Model):
    created_at = models.DateTimeField(default=datetime.now)


class Item(models.Model):
    the_model = models.ForeignKey(TheModel, on_delete=models.CASCADE, related_name='items')

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

qs = models.TheModel.objects.all()
qs = qs.annotate(contained_items=Count('items'))
result = qs.values('created_at__date').annotate(
    total_count=Count('created_at__date'),
    models_with_contained_items=Count('created_at__date', filter=Q(contained_items__gt=2))
)

Но при этом возникает "OperationalError" "неправильное использование агрегатной функции COUNT()"

Вы можете сделать это следующим образом:

from django.db.models.functions import ExtractDay, ExtractMonth, ExtractYear

query_set = Model.objects.filter(contained_items__gt=2).annotate(day=ExtractDay('created_at'), month=ExtractMonth('created_at'), year=ExtractYear('created_at')).values('day', 'month', 'year').annotate(total_count=Count('items')).values('day', 'month', 'year', 'total_count').order_by()

Читать подробнее о Extract

Может возникнуть вопрос, почему order_by() используется в последнюю очередь? Она используется потому, что в конце Django всегда применяет упорядочивание по умолчанию, поэтому вы можете получить неожиданные результаты и не сгруппировать данные, поэтому для преодоления этой проблемы используется .order_by() без каких-либо параметров, чтобы сказать django не применять никакого упорядочивания в конце.

Вернуться на верх