Хорошие способы сортировки queryset? - Джанго



что я пытаюсь сделать, это:




  • получите 30 авторов с самым высоким счетом ( Author.objects.order_by('-score')[:30])


  • заказать авторов по last_name





какие предложения?

956   3  

3 ответов:

а как же

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(*поля)

по умолчанию результаты возвращаются с помощью QuerySet упорядочиваются упорядочивающим кортежем, заданным ordering опция В мета модели. Вы можете переопределить это на основе каждого запроса, используя order_by метод.

пример:

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

результат выше будет упорядочен по score по убыванию, затем по last_name по возрастанию. Отрицательный знак перед "-score" указывает на порядок убывания. Подразумевается порядок возрастания.

Я просто хотел проиллюстрировать, что встроенные решения (только для 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 авторов.

Comments

    Ничего не найдено.