쿼리 셋을 정렬하는 좋은 방법? -장고


111

내가하려는 것은 이것입니다.

  • 가장 높은 점수를받은 저자 30 명 확보 ( Author.objects.order_by('-score')[:30])

  • 저자를 주문하다 last_name


어떤 제안?


4
@RH : AlexMartelli의 답변을 올바른 솔루션으로 확인하는 것은 어떻습니까? (그가 그 스키트 사람 후에 무슨 일하지 않는 한 그는 ..., 더 이상 담당자를 필요로하지 않는 것이)
PaulMcG

답변:


190

이건 어떤가요

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 에있는 옵션에 의해 제공된 순서화 튜플에 따라 정렬됩니다 . order_by메서드 를 사용하여 QuerySet별로이를 재정의 할 수 있습니다 .

예:

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

위의 결과는 score내림차순, last_name오름차순으로 정렬됩니다. 앞의 음수 기호 "-score"는 내림차순 을 나타냅니다. 오름차순이 내포되어 있습니다.


1
@Alex : 그래 지 알렉스! 훌륭했습니다. 오퍼레이터 모듈에 대해 읽어 보겠습니다!
RadiantHex 2010 년

3
Author.objects.order_by ( '-score', 'last_name') [: 30]보다 효율적입니까?
Brian Luft

4
@Brian- "더 효율적"이라는 말이 "더 정확함"을 의미한다면 그렇습니다. :) 귀하의 솔루션은 저자를 점수별로 정렬하고 동일한 점수를 가진 저자 만 알파벳순으로 정렬합니다 (이는 보조 키 작동 방식). Alex는 결과를 가져온 다음 완전히 다른 정렬 순서를 적용하는 방법을 보여줍니다 (개체 별 키 표현식을 정의하기 위해 key = operator.attrgetter 사용). 이는 OP가 요청한 것입니다.
PaulMcG 2010 년

@Paul : 그건 내가 물어 본 게 아니에요, Alex의 대답이 맞아요!
RadiantHex 2010 년

4
정렬 키 기능을 만들어 보지 않겠 lambda x: x.last_name습니까? 더 짧고 장황하며 가져 오기가 필요하지 않습니다.
Krzysztof Szularz

12

기본 제공 솔루션 (SQL 전용)이 항상 최상의 솔루션은 아니라는 점을 설명하고 싶었습니다. 처음에는 Django의 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 명을 정확하게 제공하는 Alex Martelli의 솔루션 사용 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)

보시다시피 첫 번째 결과와 동일한 결과이므로 예상대로 작동하지 않습니다.


13
결과 # 3은 점수별로 내림차순으로 정렬 된 다음 last_name IFF별로 모든 개체의 점수가 동일합니다. 문제는 결과 집합의 어떤 개체에도 동일한 점수가 없으므로 '-score'만 정렬 순서에 영향을줍니다. 3 명의 작성자 점수를 487로 설정하고 # 3을 다시 실행하십시오.
istruble 2010 년

네, 이해합니다. 기본 제공 솔루션 (SQL 전용)이 항상 최상의 솔루션은 아니라는 점을 설명하고 싶었습니다.
jathanism 2010 년

3
그것은 내가 예상했던대로 정확히했다 : 사전 식 순서 (첫 번째 정렬 키가 모두 구별되는 경우 다소 사소한 것임).
Jonas Kölker 2012 년

5

컷오프 점수에 동점을 허용하는 방법이 있습니다.

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')

이런 식으로 top_authors에서 30 명 이상의 저자를 확보 min(30,author_count)할 수 있으며 30 명 미만의 저자가있는 경우 거기에 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.