2010-01-19 8 views
17

Am Beispiel von: http://docs.djangoproject.com/en/dev/topics/db/aggregation/#filter-and-excludeFilterung nur auf Anmerkungen in Django

Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book')) 

Gibt es trotzdem die Filter nur auf die Anmerkung gelten, so dass es würde alle Publisher zurückkehrt, mit einigen einer NUM_BOOKS = 0 mit ?

+0

Sie wollen also eine Liste aller Verlage, jede kommentiert mit ihrer Anzahl von hoch bewerteten Bücher? –

+0

Ja, und diese Liste sollte Publisher enthalten, die keine Bücher oder nur Bücher mit niedrigen Bewertungen haben. –

Antwort

18

Sie können die Annotationsvariable im Filter verwenden.

publishers=Publisher.objects.annotate(num_books=Count('book')).filter(num_books__gte=2) 
+0

Nein, das ist nicht was ich will. –

+0

Uhhh ... was willst du ... – czarchaic

+0

Ich meine, ich möchte, dass alle Verleger zurückgegeben werden, und jeder Verlag sollte mit der Anzahl der Bücher mit hohen Bewertungen kommentiert werden. In der Publisher-Liste sollten daher Publisher mit weniger als zwei Büchern mit hoher Bewertung und Publisher mit Büchern mit niedriger Bewertung sowie Publisher, die überhaupt keine Bücher haben, erscheinen. Lassen Sie es mich wissen, wenn ich das besser klären kann. –

0

Sie können so etwas wie versuchen:

Book.objects.values('publisher').annotate(num_books=Count('id')) 
+1

Das wäre eine Zählung aller Bücher, nicht nur die, die eine Bewertung größer als 3 haben. –

10

Hm, ich glaube, Sie ein extra clause verwenden:

Publisher.objects.extra(select={ 
    'num_books': 'SELECT COUNT(*) ' + \ 
       'FROM <your_app>_book ' + \ 
       'WHERE <your_app>_book.publisher_id = ' + \ 
         '<your_app>_publisher.id AND ' + \ 
         'rating > 3.0' 
}) 
+0

Dies ist die beste Antwort, die ich bisher gesehen habe. Es wäre schön, wenn ich nicht raw sql verwenden müsste. –

+0

Das stimmt! Dies sollte jedoch keine Kompatibilitätsprobleme verursachen. Aber lassen Sie es mich wissen, wenn Sie einen Weg finden, dies ohne rohe SQL zu tun! – Maccesch

+1

Sie können wahrscheinlich die Methode QuerySet._as_sql (Verbindung) verwenden, um eine rohe Abfrage von Django selbst zu generieren. Kleiner Hack aber immer noch besser als es selbst zu schreiben. – farincz

5
from django.db import models 

Publisher.objects.annotate(
    num_books=models.Sum(
     models.Case(
      models.When(
       book__rating__gt=3.0, 
       then=1, 
      ), 
      default=0, 
      output_field=models.IntegerField(), 
     ) 
    ) 
).filter(
    num_books=0, 
) 
+0

Das sieht gut aus, außer am Ende nicht durch "num_books = 0" zu filtern. Alle Publisher sollten zurückgegeben werden. –

0

ich gerade diese Art von Problem. Und wenn meine Interpretation für das Problem und die erwartete Lösung richtig ist, ist dies meine Arbeitslösung:
Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0) Einfach Filter & annotieren Position. Dies geschieht in Django Version 1.9

+0

Das ist genau der gleiche Code, den ich in meiner Frage habe (nicht einmal getauscht). Das Problem, das ich hatte, ist, dass es keine Verlage zeigt, die 0 Bücher haben. Ich möchte die Publisher überhaupt nicht filtern, ich möchte nur die Anzahl filtern. –

+0

Leider habe ich vergessen, den Beispielcode zu bearbeiten. Aber das habe ich implementiert, als ich Filter & Annotate in meinem Abfrage-Set verwenden wollte. Und leider habe ich deine Frage nicht klar über 0 Buchverlag gelesen. – pupil

Verwandte Themen