ce que j'essaye de faire est ceci:
obtenir les 30 auteurs avec le score le plus élevé (
Author.objects.order_by('-score')[:30]
)ordonner les auteurs par
last_name
Aucune suggestion?
ce que j'essaye de faire est ceci:
obtenir les 30 auteurs avec le score le plus élevé ( Author.objects.order_by('-score')[:30]
)
ordonner les auteurs par last_name
Aucune suggestion?
Réponses:
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 a QuerySet
sont triés par le tuple de classement donné par l' ordering
option dans la méta du modèle. Vous pouvez remplacer cela sur une base par QuerySet à l'aide de la order_by
méthode.
Exemple:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Le résultat ci-dessus sera ordonné par ordre score
décroissant, puis par ordre last_name
croissant. Le signe négatif devant "-score"
indique l'ordre décroissant. L'ordre croissant est implicite.
lambda x: x.last_name
? C'est plus court, plus détaillé et ne nécessite aucune importation.
Je voulais juste illustrer que les solutions intégrées (SQL uniquement) ne sont pas toujours les meilleures. Au début, je pensais que la QuerySet.objects.order_by
méthode de Django acceptant plusieurs arguments, vous pouviez facilement les chaîner:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Mais cela ne fonctionne pas comme prévu. Par exemple, la première est une liste de présidents triés par score (en sélectionnant les 5 premiers pour une lecture plus facile):
>>> 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 le top 5 des 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 l' order_by
appel combiné :
>>> 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 voir, c'est le même résultat que le premier, ce qui signifie que cela ne fonctionne pas comme prévu.
Voici un moyen qui permet des égalités 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')
Vous pouvez obtenir plus de 30 auteurs dans top_authors de cette façon et si min(30,author_count)
vous avez moins de 30 auteurs.