Рассмотрим простые модели 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
показано только использование. Вы уже тестировали такие запросы? (Не было и хочу верить! :)