Considérez les modèles Django simples Eventet 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 0participants, ça va, j'ai juste besoin 0d'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.
aggregateutilisation est indiquée. Avez-vous déjà testé de telles requêtes? (Je n'ai pas et je veux croire! :)