Рассмотрим простые модели Django Eventи Participant:
class Event(models.Model):
title = models.CharField(max_length=100)
class Participant(models.Model):
event = models.ForeignKey(Event, db_index=True)
is_paid = models.BooleanField(default=False, db_index=True)
Аннотировать запрос событий легко, указав общее количество участников:
events = Event.objects.all().annotate(participants=models.Count('participant'))
Как добавить аннотацию с подсчетом отфильтрованных участников is_paid=True?
Мне нужно запрашивать все события независимо от количества участников, например, мне не нужно фильтровать по аннотированному результату. Если есть 0участники, ничего страшного, мне просто нужно 0аннотированное значение.
Пример из документации здесь не работает, так как он исключает объекты из запроса вместо аннотирования их 0.
Обновить. В Django 1.8 появилась новая функция условных выражений , поэтому теперь мы можем делать это так:
events = Event.objects.all().annotate(paid_participants=models.Sum(
models.Case(
models.When(participant__is_paid=True, then=1),
default=0,
output_field=models.IntegerField()
)))
Обновление 2. В Django 2.0 появилась новая функция условного агрегирования , см. Принятый ответ ниже.
aggregateпоказано только использование. Вы уже тестировали такие запросы? (Не было и хочу верить! :)