[Re:Django] 9. QuerySet Method (3)

Magit·2020년 5월 6일
0

Django

목록 보기
9/13

.order_by()

정렬의 기준을 정해준다. 아무것도 명시하지 않으면 오름차순, -가 명시되면 내림차순으로 정렬된다.

Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline')
# 전체 Entry에서 발행일자가 2005년인 데이터를 필터링한다.
# 그리고 이를 정렬하는데 발행일자를 기준으로 내림차순을 먼저 정렬한다.
# 그 다음에 발행일자가 같을 경우 headline을 기준으로 오름차순으로 정렬한다.
Entry.objects.order_by('?')
# 랜덤 정렬을 원할 경우 `?` 를 사용하면 된다.
Entry.objects.order_by('blog__name', 'headline')
# 다른 모델에 있는 필드를 기준으로 정렬할 때는 underscore 2개를 사용한다.

다른 모델과 관계인 필드를 기준으로 하려면, Django는 관련 모델의 기본 순을 정렬하거나, Meta.ordering이 지정되지 않으면 모델의 기본키를 기준으로 한다.

# 순서가 지정되지 않은 경우
Entry.objects.order_by('blog')

# 위 코드는 아래와 같다.
Entry.objects.order_by('blog__id')

# name 순으로 정렬할 경우
Entry.objects.order_by('blog__name')

# asc()나 desc()를 사용해 순서를 지정할 수 있다.
Entry.objects.order_by(Coalesce('summary', 'headline').desc())

# asc(), desc()는 null 값이 정렬되는 방법을 제어하는 인수(nulls_first, nulls_last)를 가지고 있다.
Entry.objects.order_by(Lower('headline').desc())
# Lower로 대소문자를 구분하여 정렬할 수 있다.

일반적인 정렬에서는 대소문자를 특별히 구분하지 않지만, 데이터는 대소문자도 다르게 정렬된다. 그러므로 정렬의 기준이 되는 필드를 Lower로 처리하고 정렬해야 원하는 값이 나온다.

# headline은 무시되고, pub_date 기준으로 정렬된다.
Entry.objects.order_by('headline').order_by('pub_date')

위의 코드처럼 order_by가 2개로 구분되면 가장 나중에 실행된 order_by 를 기준으로 덮어씌워진다. headline을 기준으로 먼저 정렬된 상태를 유지하고 pub_date로 따로 정렬하는 걸 원했다면 하나의 order_by안에 두 필드네임을 명시해야한다.

QuerySet.ordered 는 QuerySet이 어떤 방식으로든 정렬된 경우에 True를 반환한다.

class Event(Model):
  parent = models.ForeignKey(
      'self',
      on_delete=models.CASCADE,
      related_name='children'
  )
  date = models.DateField()

Event.objects.order_by('children__date')
# 다중값 필드를 지정하여 정렬할 수 있다(MTM, ForeignKey의 역관계)

각 이벤트에 잠재적으로 여러 주문 데이터가 있을 경우 새 QuerySet이 여러번 반환되므로, 다중값 필드를 사용하여 결과를 정렬할 때는 주의해야한다.

정렬에 추가한 각 필드는 DB 비용이 발생한다. 외래키도 암시적으로 포함된다.

profile
이제 막 배우기 시작한 개발자입니다.

0개의 댓글