Ich versuche Folgendes zu tun:
Holen Sie sich die 30 Autoren mit der höchsten Punktzahl (
Author.objects.order_by('-score')[:30]
)Bestellen Sie die Autoren von
last_name
Irgendwelche Vorschläge?
Ich versuche Folgendes zu tun:
Holen Sie sich die 30 Autoren mit der höchsten Punktzahl ( Author.objects.order_by('-score')[:30]
)
Bestellen Sie die Autoren von last_name
Irgendwelche Vorschläge?
Antworten:
Wie wäre es mit
import operator
auths = Author.objects.order_by('-score')[:30]
ordered = sorted(auths, key=operator.attrgetter('last_name'))
In Django 1.4 und höher können Sie bestellen, indem Sie mehrere Felder angeben.
Referenz: https://docs.djangoproject.com/de/dev/ref/models/querysets/#order-by
order_by (* Felder)
Standardmäßig werden die von a zurückgegebenen Ergebnisse nach QuerySet
dem Bestelltupel sortiert, das durch die ordering
Option in der Meta des Modells angegeben wird. Sie können dies mit der order_by
Methode pro QuerySet überschreiben .
Beispiel:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Das obige Ergebnis wird nach score
absteigend und dann nach last_name
aufsteigend geordnet . Das negative Vorzeichen vor "-score"
zeigt die absteigende Reihenfolge an. Aufsteigende Reihenfolge ist impliziert.
lambda x: x.last_name
? Es ist kürzer, ausführlicher und benötigt keinen Import.
Ich wollte nur veranschaulichen, dass die integrierten Lösungen (nur SQL) nicht immer die besten sind. Zuerst dachte ich, da Djangos QuerySet.objects.order_by
Methode mehrere Argumente akzeptiert, könnte man sie leicht verketten:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Aber es funktioniert nicht wie erwartet. Beispiel: Zunächst wird eine Liste der Präsidenten nach Punktzahl sortiert (Auswahl der Top 5 zum leichteren Lesen):
>>> 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)
Verwenden der Lösung von Alex Martelli, die genau die fünf besten Personen liefert, sortiert nach 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)
Und jetzt der kombinierte order_by
Anruf:
>>> 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)
Wie Sie sehen, ist es das gleiche Ergebnis wie das erste, was bedeutet, dass es nicht wie erwartet funktioniert.
Hier ist ein Weg, der Unentschieden für den Cut-Off-Score ermöglicht.
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')
Auf diese Weise erhalten Sie möglicherweise mehr als 30 Autoren in top_authors, min(30,author_count)
falls Sie weniger als 30 Autoren haben.