Considérez les modèles Django simples Event
et 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)
Il est facile d'annoter la requête d'événements avec le nombre total de participants:
events = Event.objects.all().annotate(participants=models.Count('participant'))
Comment annoter avec le nombre de participants filtrés par is_paid=True
?
J'ai besoin d'interroger tous les événements quel que soit le nombre de participants, par exemple je n'ai pas besoin de filtrer par résultat annoté. S'il y a des 0
participants, ça va, j'ai juste besoin 0
d'une valeur annotée.
L' exemple de la documentation ne fonctionne pas ici, car il exclut les objets de la requête au lieu de les annoter avec 0
.
Mettre à jour. Django 1.8 a une nouvelle fonctionnalité d'expressions conditionnelles , donc maintenant nous pouvons faire comme ceci:
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()
)))
Mise à jour 2. Django 2.0 a une nouvelle fonctionnalité d' agrégation conditionnelle , voir la réponse acceptée ci-dessous.
aggregate
utilisation est indiquée. Avez-vous déjà testé de telles requêtes? (Je n'ai pas et je veux croire! :)