it-swarm.com.de

Gute Möglichkeiten, einen Abfragesatz zu sortieren? - Django

was ich versuche zu tun, ist Folgendes:

  • erhalte die 30 Autoren mit der höchsten Punktzahl (Author.objects.order_by('-score')[:30])

  • ordne die Autoren nach last_name


Irgendwelche Vorschläge?

98
RadiantHex

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 neuer 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 einem QuerySet zurückgegebenen Ergebnisse nach dem durch die Option ordering in der Meta des Modells angegebenen Bestell-Tupel sortiert. Sie können dies pro QuerySet überschreiben, indem Sie order_by Methode.

Beispiel:

ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]

Das obige Ergebnis wird nach score absteigend sortiert, dann nach last_name aufsteigend. Das negative Vorzeichen vor "-score" zeigt absteigende Reihenfolge an. Aufsteigende Reihenfolge wird vorausgesetzt.

173
Alex Martelli

Ich wollte nur veranschaulichen, dass die integrierten Lösungen (nur SQL) nicht immer die besten sind. Zuerst dachte ich, weil Djangos QuerySet.objects.order_by-Methode akzeptiert mehrere Argumente, Sie können sie leicht verketten:

ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]

Aber es funktioniert nicht wie erwartet. Das erste Beispiel ist eine Liste der Präsidenten, sortiert nach Punktzahl (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)

Mit Alex Martellis Lösung, die die Top 5 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 die 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 dasselbe Ergebnis wie das erste, was bedeutet, dass es nicht wie erwartet funktioniert.

11
jathanism

Hier ist ein Weg, der Unentschieden für den Cut-Off-Score zulässt.

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 in top_authors möglicherweise mehr als 30 Autoren, und die Funktion min(30,author_count) ist vorhanden, wenn Sie weniger als 30 Autoren haben.

5
istruble