Rozważmy prostych modeli Django Event
i Participant
:Jak filtrować obiekty w celu zliczania komentarzy w Django?
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)
Łatwo jest opisywanie dalszych wydarzeń z ogólnej liczby uczestników:
events = Event.objects.all().annotate(participants=models.Count('participant'))
Jak adnotacje z liczbą uczestników filtrowany przez is_paid=True
?
Muszę wysłać zapytanie wszystkie zdarzenia niezależnie od liczby uczestników, np. Nie muszę filtrować według adnotowanych wyników. Jeśli są uczestnicy 0
, to w porządku, po prostu potrzebuję 0
w adnotowanej wartości.
Tu nie działa example from documentation, ponieważ wyklucza obiekty z kwerendy zamiast ich adnotacji z 0
.
Aktualizacja. Django 1.8 posiada nowy conditional expressions feature, więc teraz możemy zrobić tak:
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()
)))
Aktualizacja 2. Django 2.0 posiada nową funkcję Conditional aggregation zobacz the accepted answer poniżej.
To wygląda świetnie! :) – rudyryk
BTW, nie ma takiego przykładu przez link dokumentacji, pokazane jest tylko użycie 'agregatu'. Czy przetestowałeś już takie zapytania? (Nie mam i chcę wierzyć! :) – rudyryk
Mam. Oni pracują. Naprawdę trafiłem na dziwną łatę, w której stare (super-skomplikowane) podzapytanie przestało działać po aktualizacji do Django 2.0 i udało mi się zastąpić ją super-prostą filtrowaną liczbą. Na adnotacjach znajduje się lepszy przykład do doc pracy, więc wciągnę to teraz. – Oli