5 votes

Dans Django, existe-t-il un moyen d'agréger les relations avec une condition sur l'objet lié ?

La documentation sur l'agrégation de Django donne cet exemple qui compte le nombre de Book liés à chaque Publisher et renvoie un ensemble de requêtes avec les 5 premiers éditeurs annotés avec leur nombre de livres (comme si on ajoutait un nouveau champ avec ce nombre) :

>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323

Mais j'ai besoin de compter seulement un type spécifique de livre. Quelque chose comme.

>>> pubs = Publisher.objects.annotate(num_books=Count('book__type="nonfiction"')).order_by('-num_books')[:5]

Existe-t-il un filtre que je peux utiliser pour y parvenir ou dois-je recourir au SQL brut ?

Ce qui précède est l'exemple de docs analogue à mon vrai problème, qui est d'identifier et de quantifier les plus grands groupes médicaux en fonction du nombre d'hôpitaux dans leur système, lorsque les systèmes et les hôpitaux sont tous deux modélisés comme des soins de santé. Entity s :

>>> biggest_systems = Entity.objects.filter(relationships__type_id=NAME_TO_TYPE_ID.get('hospital')).annotate(num_hospitals=Count('relationships')).order_by('-num_hospitals')[:5]
>>> biggest_systems[0].num_hospitals
25

relationships est un champ M2M d'Entity avec une table de passage, type_id est également un champ dans Entity :

class Entity(models.Model):
    id = models.AutoField(verbose_name='ID',primary_key=True, db_column='ID') 
    type_id = models.IntegerField(verbose_name='detailed type',db_column='TypeID', blank=True, editable=True, choices=ENTITYTYPE_CHOICES, help_text="A category for this healthcare entity.")
    relationships = models.ManyToManyField('self', verbose_name='affiliated with', through='EntityRelationship', symmetrical=False, related_name='related_to+')

4voto

jpic Points 17307

Voir Ordre des clauses annotate() et filter() :

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

Ou dans votre cas :

Publisher.objects.filter(book__type='nonfiction').annotate(num_books=Count('book'))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X