Розглянемо прості моделі Джанго 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
показано лише використання. Ви вже протестували такі запити? (У мене немає і я хочу вірити! :)