quello che sto cercando di fare è questo:
ottieni i 30 autori con il punteggio più alto (
Author.objects.order_by('-score')[:30]
)ordina gli autori per
last_name
Eventuali suggerimenti?
quello che sto cercando di fare è questo:
ottieni i 30 autori con il punteggio più alto ( Author.objects.order_by('-score')[:30]
)
ordina gli autori per last_name
Eventuali suggerimenti?
Risposte:
Che dire
import operator
auths = Author.objects.order_by('-score')[:30]
ordered = sorted(auths, key=operator.attrgetter('last_name'))
In Django 1.4 e versioni successive è possibile ordinare fornendo più campi.
Riferimento: https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by
order_by (* campi)
Per impostazione predefinita, i risultati restituiti da a QuerySet
sono ordinati in base alla tupla di ordinamento fornita ordering
dall'opzione nel Meta del modello. È possibile sovrascriverlo in base a QuerySet utilizzando il order_by
metodo.
Esempio:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Il risultato sopra sarà ordinato per ordine score
discendente, quindi last_name
crescente. Il segno negativo davanti a "-score"
indica l'ordine decrescente. L'ordine crescente è implicito.
lambda x: x.last_name
? È più breve, più dettagliato e non necessita di alcuna importazione.
Volevo solo illustrare che le soluzioni integrate (solo SQL) non sono sempre le migliori. All'inizio ho pensato che, poiché il QuerySet.objects.order_by
metodo di Django accetta più argomenti, potresti facilmente concatenarli:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Ma non funziona come ti aspetteresti. Caso in questione, il primo è un elenco di presidenti ordinati per punteggio (selezionando i primi 5 per una lettura più 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)
Utilizzando la soluzione di Alex Martelli che fornisce accuratamente le prime 5 persone ordinate per 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)
E ora la order_by
chiamata combinata :
>>> 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)
Come puoi vedere è lo stesso risultato del primo, il che significa che non funziona come ti aspetteresti.
Ecco un modo che consente i pareggi per il punteggio limite.
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')
Puoi avere più di 30 autori in top_authors in questo modo ed min(30,author_count)
è possibile che tu abbia meno di 30 autori.