91 votes

Équivalent de Django pour le comte et le groupe de

J’ai un modèle qui ressemble à ceci :

Je veux select count (juste le nombre) des éléments pour chaque catégorie, et en SQL, il serait donc aussi simple que cela :

Yat-il un équivalent de le faire « la voie de Django » ? Ou simple SQL n’est la seule option ? Je suis familier avec la méthode de comptage () en Django, mais je ne vois pas comment le groupe par déparerait là.

131voto

michael Points 1233

Comme je viens de le découvrir, voici comment procéder avec l’agrégation de Django 1.1 API :

58voto

Carl Meyer Points 30736

(Mise à jour: Plein ORM agrégation de prise en charge est désormais inclus dans Django 1.1. Fidèle à l'avertissement ci-dessous sur l'utilisation des Api privées, la méthode décrite ici ne travaille plus dans l'après-1.1 versions de Django. Je n'ai pas creusé pour comprendre pourquoi; si vous êtes sur la 1.1 ou ultérieure, vous devez utiliser le réel de l'agrégation de l'API de toute façon.)

L'agrégation principal soutien était déjà là en 1.0; il est juste de sans-papiers, non pris en charge, et n'a pas une amicale de l'API sur le dessus de celui-ci encore. Mais ici, c'est comment vous pouvez l'utiliser de toute façon jusqu'à 1.1 arrive (à vos risques et périls, et en pleine connaissance de la requête.group_by attribut n'est pas partie d'une API publique et le risque de changement):

query_set = Item.objects.extra(select={'count': 'count(1)'}, 
                               order_by=['-count']).values('count', 'category')
query_set.query.group_by = ['category_id']

Si vous parcourir query_set, chaque valeur retournée sera un dictionnaire avec une "catégorie" et un "comte".

Vous n'avez pas à l'ordre par le comte ici, c'est juste inclus pour montrer comment c'est fait (il doit être fait dans la .extra() appel, pas ailleurs dans le queryset de la construction de la chaîne). Aussi, vous pourriez tout aussi bien dire count(id) au lieu de compter(1), mais celle-ci peut être plus efficace.

Notez également que lors de la configuration .de la requête.group_by, les valeurs doivent être réels DB noms de colonne ('category_id') pas de Django les noms de champ ("catégorie"). C'est parce que vous êtes à peaufiner les requêtes internes à un niveau où tout est dans la bd, pas de Django termes.

56voto

Daniel Points 1032

Depuis que j'ai été un peu confus sur la façon de regroupement dans Django 1.1 fonctionne, j'ai pensé que j'avais élaborée ici sur comment exactement vous allez utiliser. Tout d'abord, pour répéter ce que Michael a dit:

Ici, comme je viens de le découvrir, comment faire avec le Django 1.1 agrégation de l'API:

from django.db.models import Count
theanswer = Item.objects.values('category').annotate(Count('category'))

Notez également que vous devez from django.db.models import Count!

Cela permettra de sélectionner uniquement les catégories, et d'ajouter une annotation appelés category__count. En fonction de la valeur par défaut de la commande de ce peut être tout ce dont vous avez besoin, mais si la valeur par défaut de la commande utilise un champ autre que category cela ne fonctionnera pas. La raison pour cela est que les champs requis pour la commande sont également sélectionnés et faire de chaque ligne unique, de sorte que vous ne sera pas obtenir les choses regroupées comme vous le souhaitez. Un moyen rapide de résoudre ce problème est de réinitialiser la commande:

Item.objects.values('category').annotate(Count('category')).order_by()

Cela devrait produire les résultats que vous souhaitez. Pour définir le nom de l'annotation, vous pouvez utiliser:

...annotate(mycount = Count('category'))...

Ensuite, vous aurez une annotation appelés mycount dans les résultats.

Tout le reste sur le groupement a été très simple pour moi. Soyez sûr de vérifier le Django d'agrégation de l'API pour des informations plus détaillées.

2voto

S.Lott Points 207588

Comment est-ce ? (Autre que ralentir.)

Il a l’avantage d’être court, même si il aller chercher un grand nombre de lignes.


Edit.

La version d’une seule requête. BTW, c’est souvent plus rapide que sélectionnez COUNT(*) dans la base de données. Essayez-le pour voir.

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