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 не применять никакого упорядочивания в конце.