¿Cómo filtrar objetos para la anotación de recuento en Django?
Considere modelos simples de DjangoEvent
yParticipant
:
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 la consulta de eventos con el número total de participantes:
events = Event.objects.all().annotate(participants=models.Count('participant'))
Cómo anotar con recuento de participantes filtrados poris_paid=True
?
Necesito consultartodos los eventos independientemente del número de participantes, p. No necesito filtrar por resultado anotado. Si hay0
participantes, está bien, solo necesito0
en valor anotado.
losejemplo de documentación no funciona aquí, porque excluye objetos de la consulta en lugar de anotarlos con0
.
Actualizar. Django 1.8 tiene nuevocaracterística de expresiones condicionales, así que ahora podemos hacer esto:
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 nuevoAgregación condicional característica, verla respuesta aceptada abajo.