Je recherche un modèle:
Members.objects.all()
Et ça revient:
Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop
Ce que je veux, c'est connaître la meilleure façon Django de lancer une group_by
requête dans ma base de données, comme:
Members.objects.all().group_by('designation')
Ce qui ne fonctionne pas, bien sûr. Je sais que nous pouvons faire quelques astuces django/db/models/query.py
, mais je suis simplement curieux de savoir comment le faire sans patcher.
python
django
django-models
Simplyharsh
la source
la source
Members.objects.filter(date=some_date).values('designation').annotate(dcount=Count('designation'))
Members.objects.order_by('disignation').values('designation').annotate(dcount=Count('designation'))
Une solution simple, mais pas la bonne, consiste à utiliser du SQL brut :
Une autre solution consiste à utiliser la
group_by
propriété:Vous pouvez maintenant parcourir la variable des résultats pour récupérer vos résultats. Notez que cela
group_by
n'est pas documenté et pourrait être modifié dans la future version de Django.Et ... pourquoi voulez-vous l'utiliser
group_by
? Si vous n'utilisez pas d'agrégation, vous pouvez utiliserorder_by
pour obtenir un résultat similaire.la source
Vous pouvez également utiliser la
regroup
balise de modèle pour regrouper par attributs. De la documentation:Ressemble à ça:
Il fonctionne également sur
QuerySet
s je crois.source: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#regroup
modifier: notez que la
regroup
balise ne fonctionne pas comme vous vous y attendez si votre liste de dictionnaires n'est pas triée par clé. Cela fonctionne de manière itérative. Triez donc votre liste (ou ensemble de requêtes) par la clé du mérou avant de la passer à laregroup
balise.la source
Vous devez faire du SQL personnalisé comme illustré dans cet extrait:
SQL personnalisé via une sous-requête
Ou dans un gestionnaire personnalisé comme indiqué dans les documents Django en ligne:
Ajout de méthodes Manager supplémentaires
la source
Django ne prend pas en charge les groupes libres par requêtes . Je l'ai appris de très mauvaise façon. ORM n'est pas conçu pour prendre en charge des choses comme ce que vous voulez faire, sans utiliser de SQL personnalisé. Vous êtes limité à:
cr.execute
phrases (et une analyse à la main du résultat)..annotate()
(le regroupement par phrases est effectué dans le modèle enfant pour .annotate (), dans des exemples comme l'agrégation lines_count = Count ('lines'))).Sur un ensemble de requêtes,
qs
vous pouvez appelerqs.query.group_by = ['field1', 'field2', ...]
mais il est risqué si vous ne savez pas quelle requête éditez-vous et n'avez aucune garantie que cela fonctionnera et ne cassera pas les internes de l'objet QuerySet. De plus, c'est une API interne (non documentée) à laquelle vous ne devez pas accéder directement sans risquer que le code ne soit plus compatible avec les futures versions de Django.la source
Il existe un module qui vous permet de regrouper les modèles Django et de continuer à travailler avec un QuerySet dans le résultat: https://github.com/kako-nawao/django-group-by
Par exemple:
«book / books.html»
La différence des
annotate
/ deaggregate
base des requêtes Django est l'utilisation des attributs d'un domaine connexe, par exemplebook.author.last_name
.Si vous avez besoin des PK des instances qui ont été regroupées, ajoutez l'annotation suivante:
REMARQUE:
ArrayAgg
est une fonction spécifique à Postgres, disponible à partir de Django 1.9: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/aggregates/#arrayaggla source
values
méthode. C'est à des fins différentes, je pense.values
est un SQLselect
tandis quegroup_by
est un SQLgroup by
(comme son nom l'indique ...). Pourquoi le downvote? Nous utilisons ce code en production pour implémenter desgroup_by
instructions complexes .group_by
"se comporte principalement comme la méthode des valeurs, mais avec une différence ..." Le doc ne mentionne pas SQLGROUP BY
et le cas d'utilisation qu'il fournit ne suggère pas qu'il ait quoi que ce soit à voir avec SQLGROUP BY
. Je retirerai le vote négatif lorsque quelqu'un aura clarifié cela, mais ce document est vraiment trompeur.values
, j'ai trouvé que je manquais que celavalues
fonctionne comme un GROUP BY. C'est de ma faute. Je pense qu'il est plus simple à utiliseritertools.groupby
que ce groupe de django quand ilvalues
est insuffisant.group by
précède avec un simplevalues
appel - avec ou sansannotate
et sans tout récupérer de la base de données. Votre suggestion deitertools.groupby
travaux pour les petits ensembles de données mais pas pour plusieurs milliers d'ensembles de données que vous souhaitez probablement mettre en page. Bien sûr, à ce stade, vous devrez de toute façon penser à un index de recherche spécial qui contient des données préparées (déjà groupées).Le document indique que vous pouvez utiliser des valeurs pour regrouper l'ensemble de requêtes.
Vous pouvez trouver tous les livres et les regrouper par nom en utilisant ce code:
Vous pouvez regarder une feuille de cheet ici .
la source
Si je ne me trompe pas, vous pouvez utiliser, quel que soit l'ensemble de requêtes .group_by = [' field ']
la source
vous devez d'abord importer Sum puis ..
la source