2017-10-14 12 views
2

inspirer de ce modèle dans la documentation Django: Aggregation and AvgDjango queryset - Filtrage des objets de table liés avant l'agrégation

Il y a un queryset comme ceci:

Author.objects.annotate(average_rating=Avg('book__rating')) 

qui renvoie tous les auteurs annotés par le taux moyen de l'ensemble des leurs livres. Et si je veux interroger les auteurs annotés par le taux moyen de leurs livres qui ont été publiés par exemple en 2016.

Notez que je veux obtenir des résultats avec le moins de requêtes possible.

+0

Pouvez-vous décrire les modèles de 'Author' et' Book'? –

+0

Ils sont au début de la page de documentation que j'ai référencé dans la première ligne. –

Répondre

4

Étant donné que le modèle Book a un attribut pubdate qui est un DateField, vous pouvez utiliser:

from datetime import datetime 

y2016 = datetime(2016,1,1) 

Author.objects.filter(book__pubdate__lt=y2016) \ 
       .annotate(average_rating=Avg('book__rating'))

Alors book__pubdate__lt signifie que vous vérifiez que le pubdate du book est inférieur à (__lt) y2016 (la premier janvier 2016).

Si le filter est appliqué avant leannotate il filtrera les livres qui sont loin publised avant 2016. Notez que les auteurs qui n'ont pas publised avant 2016 ne dans le QuerySet résultant. Mais cela semble logique (puisque vous ne pouvez pas calculer une moyenne sur un ensemble vide).

+1

Est-ce que cela ne filtrera pas seulement les auteurs ayant au moins un livre avant 2016, mais annotera quand même ceux avec la moyenne de ** tous ** leurs livres? – schwobaseggl

+0

@schwobaseggl: afaik, ce ne sera pas. Les filtres sans livres ne seront pas dans le résultat. Mais basé sur d'autres requêtes, il laissera donc de côté les livres qui sont publiés avant 2016. –

+0

book__pubdate__lt = y2016 signifie seulement chercher des auteurs dont les livres ont été publiés avant 2016. il ne filtrera pas les livres par pubdate. –