Django 템플릿에서 관련 항목 정렬


87

DJango 템플릿에서 관련 항목 세트를 정렬 할 수 있습니까?

즉,이 코드 (명확성을 위해 HTML 태그가 생략 됨) :

{% for event in eventsCollection %}
   {{ event.location }}
   {% for attendee in event.attendee_set.all %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

내가 원하는 거의 정확하게 표시합니다 . 내가 변경하고 싶은 유일한 것은 성으로 정렬 할 참석자 목록입니다. 나는 다음과 같이 말하려고 시도했습니다.

{% for event in events %}
   {{ event.location }}
   {% for attendee in event.attendee_set.order_by__last_name %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

아아, 위의 구문은 작동하지 않으며 (빈 목록이 생성됨) 내가 생각했던 다른 변형도 없습니다 (많은 구문 오류가보고되었지만 기쁨은 없음).

물론 내 관점에서 일종의 정렬 된 참석자 목록을 생성 할 수는 있지만 그것은 추하고 깨지기 쉬운 (그리고 추악한 것을 언급 했습니까) 해결책입니다.

말할 필요도없이, 어쨌든 나는 그것을 말할 것이다. 나는 온라인 문서를 숙독하고 도움이되는 것을 찾지 않고 Stack Overflow와 django-user의 아카이브를 검색했다 (아, 쿼리 세트 만 사전 dictsort라면 직업이지만 그렇지 않습니다)

=============================================

Tawmas의 답변을 수락 한 후 추가 생각을 추가하도록 편집되었습니다.


Tawmas는 내가 제시 한대로 문제를 정확히 해결했지만 해결책은 내가 예상 한 것과는 달랐습니다. 그 결과 다른 상황에서도 사용할 수있는 유용한 기술을 배웠습니다.

Tom의 대답은 내가 OP에서 이미 언급 한 접근 방식을 제안했고 "추악한"것으로 잠정적으로 거부했습니다.

"못생긴"은 직감 반응이었고, 나는 그것에 무엇이 잘못되었는지 명확히하고 싶었습니다. 그렇게하면서 나는 그것이 추악한 접근 방식 인 이유가 렌더링 할 템플릿에 쿼리 세트를 전달한다는 생각에 매 달렸 기 때문이라는 것을 깨달았습니다. 이 요구 사항을 완화하면 작동해야 할 추악한 접근 방식이 있습니다.

나는 아직 시도했지만 오히려 검색어 세트를 전달하는 대신, 뷰 코드는 이벤트의 다음 해당 참석자에 대한 쿼리 세트 각 이벤트 장식 목록 생성 쿼리 집합을 통해 반복한다고 가정하지 않은 WAS , 분류를 (또는 필터링 또는 무엇이든) 원하는 방식으로. 다음과 같이 :

eventCollection = []   
events = Event.object.[filtered and sorted to taste]
for event in events:
   event.attendee_list = event.attendee_set.[filtered and sorted to taste]
   eventCollection.append(event)

이제 템플릿은 다음과 같습니다.

{% for event in events %}
   {{ event.location }}
   {% for attendee in event.attendee_list %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

단점은 모든 이벤트를 한 번에 "실현"해야한다는 것입니다. 이벤트가 많으면 문제가 될 수 있습니다. 물론 페이지 매김을 추가 할 수 있지만 이는보기를 상당히 복잡하게 만듭니다.

장점은 "표시 할 데이터 준비"코드가보기에 속한보기에 표시되어 표시를 위해보기에서 제공하는 데이터의 서식 지정에 템플릿이 집중할 수 있다는 것입니다. 이것은 옳고 적절합니다.

그래서 내 계획은 큰 테이블에는 Tawmas의 기술을 사용하고 작은 테이블에는 위의 기술을 사용하고 크고 작은 정의는 독자에게 맡기는 것입니다 (웃음).

답변:


135

다음과 같이 참석자 모델에서 순서를 지정해야합니다. 예를 들어 (모델 클래스의 이름이 Attendee라고 가정) :

class Attendee(models.Model):
    class Meta:
        ordering = ['last_name']

자세한 내용 은 설명서 를 참조하십시오.

편집 . 또 다른 해결책은 템플릿에서 액세스 할 수있는 속성을 이벤트 모델에 추가하는 것입니다.

class Event(models.Model):
# ...
@property
def sorted_attendee_set(self):
    return self.attendee_set.order_by('last_name')

필요에 따라 더 많이 정의 할 수 있습니다.


의견을 보내 주셔서 감사합니다. 표시 순서를 참석자의 영구적 인 속성으로 만들고 싶은 경우에만 작동합니다. 예를 들어, 등록을받은 날짜별로 정렬 된 참석자를 표시하고 싶을 수 있으므로 참석자를위한 공간이 없다는 알림을 받아야하는 참석자를 알 수 있습니다.
Dale Wilson

대체 솔루션을 추가했습니다. 필요한 유연성을 제공해야합니다.
tawmas

@Mark Indeed는 그렇습니다. 내가 이해하는 한 @propertygetter 또는 setter가 관련되어 있지 않기 때문에 여기에 과잉입니다. stackoverflow.com/questions/1554546/…
Rick Westera

템플릿에 엄격하게 필요하지는 않지만 여기에 @property 가 애플리케이션 코드에서 더 깔끔하게 액세스 할 수 있다는 것을 알았습니다 .하지만 약간의 성능 저하가 있습니다 (랩톱에서 30ns 미만). 물론 이것은 스타일과 매우 주관적인 문제입니다.
tawmas

두 속성을 기준으로 집합을 정렬하려는 경우 다음과 같은 명령이 있습니다. class Meta : ordering = [ 'last_name', 'first_name']
Tms91

135

템플릿 필터 dictsort https://docs.djangoproject.com/en/dev/ref/templates/builtins/#std:templatefilter-dictsort를 사용할 수 있습니다.

이것은 작동합니다.

{% for event in eventsCollection %}
   {{ event.location }}
   {% for attendee in event.attendee_set.all|dictsort:"last_name" %}
     {{ attendee.first_name }} {{ attendee.last_name }}
   {% endfor %}
 {% endfor %}

22
좋아요! 그리고 궁금해하는 사람들을 위해,도있다 dictsortreversed: docs.djangoproject.com/en/dev/ref/templates/builtins/...
미카엘

1
내 원래 게시물에서 인용하자면 : 아, 쿼리 세트 만 사전 dictsort이면 작업을 수행 할 수 있지만 그렇지 않습니다.
Dale Wilson

나는 이것이 실제로는 적어야한다고 생각하며 레코드를 가져 오기 전에 모델이 정렬을 처리하도록합니다.
acpmasquerade

1
@DaleWilson, 나는 실제로 dictsort당신과 거의 똑같은 코드에서 제대로 작업하고 있습니다. 흥미롭게도 쿼리 세트에서 잘 작동하는 것 같습니다.
mlissner 2015-08-26

2
더 명확하게하기 위해 공백이 중요합니다. {% for attendee in event.attendee_set.all|dictsort:"last_name" %}참석자 {% for attendee in event.attendee_set.all | dictsort:"last_name" %}를 정렬 하지만 for 루프의 출력을 정렬하려고 시도하고 for.
mattsl

3

한 가지 해결책은 사용자 정의 templatag를 만드는 것입니다.

@register.filter
def order_by(queryset, args):
    args = [x.strip() for x in args.split(',')]
    return queryset.order_by(*args)

다음과 같이 사용하십시오.

{% for image in instance.folder.files|order_by:"original_filename" %}
   ...
{% endfor %}

0

regroup 은 원하는 것을 할 수 있어야하지만 뷰에서 원하는 방식으로 주문할 수없는 이유가 있습니까?


보기에서 순서를 지정하려면 이벤트를 반복하고 각 이벤트에 대해 해당 이벤트와 관련된 일종의 참석자의 컨테이너를 적절하게 정렬 된 순서로 만든 다음 전체 컨테이너 컬렉션을 다음과 같은 형식으로 템플릿에 전달해야합니다. 같은 템플릿이 참석자의 적절한 수집을 찾을 수 있습니다 것이 이벤트를 통해 반복. 내가 말했듯이 할 수는 있지만 좋은 해결책은 아닙니다. 뷰와 템플릿 사이에 너무 많은 커플 링, 병렬 반복 등이 필요합니다. 일반적인 문제에 대한 더 나은 솔루션을 원했습니다.
Dale Wilson

나는 재편성을 보았지만 내가 원하는 것을하지 않는 것 같았다. 특히 문서에는 다음과 같이 나와 있습니다. [quote] {% regroup %}은 입력을 주문하지 않습니다! 우리의 예는 사람 목록이 처음에 성별로 정렬되었다는 사실에 의존합니다. [endquote]
Dale Wilson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.