ce que j'essaie de faire est la suivante:
obtenir les 30 auteurs avec le score le plus élevé (Author.objects.order_by('-score')[:30]
)
ordonner aux auteurs par last_name
Aucune suggestion?
Qu'en est-il de
import operator
auths = Author.objects.order_by('-score')[:30]
ordered = sorted(auths, key=operator.attrgetter('last_name'))
Dans Django 1.4 et plus récent, vous pouvez commander en fournissant plusieurs champs.
Référence: https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by
order_by (* champs)
Par défaut, les résultats renvoyés par un QuerySet
sont classés par le tuple de classement donné par l’option ordering
dans la méta du modèle. Vous pouvez remplacer ceci sur une base individuelle de QuerySet à l'aide de la commande order_by
méthode.
Exemple:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Le résultat ci-dessus sera ordonné par score
décroissant, puis par last_name
Ascendant. Le signe négatif devant "-score"
indique un ordre décroissant. L'ordre croissant est impliqué.
Je voulais simplement illustrer le fait que les solutions intégrées (SQL uniquement) ne sont pas toujours les meilleures. Au début, je pensais que parce que Django's QuerySet.objects.order_by
La méthode accepte plusieurs arguments, vous pouvez facilement les chaîner:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Mais cela ne fonctionne pas comme prévu. Un exemple typique est une liste de présidents triés par score (en sélectionnant les 5 meilleurs pour en faciliter la lecture):
>>> auths = Author.objects.order_by('-score')[:5]
>>> for x in auths: print x
...
James Monroe (487)
Ulysses Simpson (474)
Harry Truman (471)
Benjamin Harrison (467)
Gerald Rudolph (464)
En utilisant la solution d'Alex Martelli qui fournit avec précision les 5 meilleures personnes triées par last_name
:
>>> for x in sorted(auths, key=operator.attrgetter('last_name')): print x
...
Benjamin Harrison (467)
James Monroe (487)
Gerald Rudolph (464)
Ulysses Simpson (474)
Harry Truman (471)
Et maintenant, le combiné order_by
appel:
>>> myauths = Author.objects.order_by('-score', 'last_name')[:5]
>>> for x in myauths: print x
...
James Monroe (487)
Ulysses Simpson (474)
Harry Truman (471)
Benjamin Harrison (467)
Gerald Rudolph (464)
Comme vous pouvez le constater, le résultat est identique à celui du premier résultat, ce qui signifie que cela ne fonctionne pas comme prévu.
Voici un moyen qui permet d’être à égalité pour le score de coupure.
author_count = Author.objects.count()
cut_off_score = Author.objects.order_by('-score').values_list('score')[min(30, author_count)]
top_authors = Author.objects.filter(score__gte=cut_off_score).order_by('last_name')
De cette façon, vous pouvez obtenir plus de 30 auteurs dans top_authors et la min(30,author_count)
existe si vous avez moins de 30 auteurs.