95 votes

Comment regrouper par ET agréger avec Django

J'ai une requête assez simple que j'aimerais faire via l'ORM, mais je n'y arrive pas

J'ai trois modèles :

Emplacement (un lieu), Attribut (un attribut qu'un lieu peut avoir), et Classement (un modèle M2M de "passage" qui contient également un champ de score).

Je veux choisir quelques attributs importants et pouvoir classer mes sites en fonction de ces attributs - c'est-à-dire que le score total le plus élevé sur tous les attributs sélectionnés est le meilleur.

Je peux utiliser le SQL suivant pour obtenir ce que je veux :

select location_id, sum(score) 
    from locations_rating 
    where attribute_id in (1,2,3) 
    group by location_id order by sum desc;

qui renvoie

 location_id | sum 
-------------+-----
          21 |  12
           3 |  11

Le plus proche que je puisse obtenir avec l'ORM est :

Rating.objects.filter(
    attribute__in=attributes).annotate(
    acount=Count('location')).aggregate(Sum('score'))

Qui retourne

{'score__sum': 23}

c'est-à-dire la somme de tous, non regroupée par lieu.

Y a-t-il un moyen de contourner ce problème ? Je pourrais exécuter le SQL manuellement, mais je préfère passer par l'ORM pour que les choses restent cohérentes.

Merci

159voto

Aamir Adnan Points 10903

Essayez ça :

Rating.objects.filter(attribute__in=attributes) \
    .values('location') \
    .annotate(score = Sum('score')) \
    .order_by('-score')

42voto

Pouvez-vous essayer ceci.

Rating.objects.values('location_id').filter(attribute__in=attributes).annotate(sum_score=Sum('score')).order_by('-score')

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