що я намагаюся зробити, це це:
отримати 30 авторів з найбільшою оцінкою (
Author.objects.order_by('-score')[:30]
)упорядкувати авторів за
last_name
Будь-які пропозиції?
що я намагаюся зробити, це це:
отримати 30 авторів з найбільшою оцінкою ( Author.objects.order_by('-score')[:30]
)
упорядкувати авторів за last_name
Будь-які пропозиції?
Відповіді:
А як на рахунок
import operator
auths = Author.objects.order_by('-score')[:30]
ordered = sorted(auths, key=operator.attrgetter('last_name'))
У Django 1.4 та новіших версіях ви можете замовити, надавши кілька полів.
Довідка: https://docs.djangoproject.com/en/dev/ref/models/querysets/#order-by
order_by (* поля)
За замовчуванням результати, повернені символом a QuerySet
, упорядковуються кортежем упорядкування, заданим ordering
опцією в мета Meta. Ви можете змінити це за принципом QuerySet, використовуючи order_by
метод.
Приклад:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Отриманий вище результат буде упорядкований у порядку score
зменшення, потім у last_name
порядку зростання. Негативний знак "-score"
вказує на порядок зменшення. Порядок зростання - мається на увазі.
lambda x: x.last_name
? Він коротший, більш багатослівний і не потребує жодного імпорту.
Я просто хотів проілюструвати, що вбудовані рішення (лише для SQL) не завжди є найкращими. Спочатку я подумав, що оскільки QuerySet.objects.order_by
метод Джанго приймає кілька аргументів, ви можете їх легко ланцюжок:
ordered_authors = Author.objects.order_by('-score', 'last_name')[:30]
Але це не працює так, як ви очікували. Справа в першу чергу - спочатку список президентів, відсортований за балами (вибравши топ 5 для легшого читання):
>>> 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)
Використовуючи рішення Алекса Мартеллі, яке точно забезпечує топ-5 людей, відсортованих за 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)
А тепер комбінований order_by
дзвінок:
>>> 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)
Як бачите, це такий же результат, як і перший, тобто він не працює так, як ви очікували.
Ось спосіб, який передбачає зв'язки для осіннього балу.
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')
Ви можете отримати більше 30 авторів у top_authors таким чином, і min(30,author_count)
якщо у вас менше 30 авторів.