Considere modelos simples de Django Event
y 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)
Es fácil anotar consultas de eventos con el número total de participantes:
events = Event.objects.all().annotate(participants=models.Count('participant'))
¿Cómo anotar con el recuento de participantes filtrados por is_paid=True
?
Necesito consultar todos los eventos independientemente del número de participantes, por ejemplo, no necesito filtrar por resultado anotado. Si hay 0
participantes, está bien, solo necesito0
valor anotado.
El ejemplo de la documentación no funciona aquí, porque excluye objetos de la consulta en lugar de anotarlos con 0
.
Actualizar. Django 1.8 tiene una nueva función de expresiones condicionales , por lo que ahora podemos hacer lo siguiente:
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()
)))
Actualización 2. Django 2.0 tiene una nueva función de agregación condicional , consulte la respuesta aceptada a continuación.
aggregate
se muestra el uso. ¿Ya ha probado este tipo de consultas? (¡No lo he hecho y quiero creer! :)