Czy można posortować zestaw powiązanych elementów w szablonie DJango?
To znaczy: ten kod (z pominiętymi tagami HTML dla przejrzystości):
{% for event in eventsCollection %}
{{ event.location }}
{% for attendee in event.attendee_set.all %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
wyświetla prawie dokładnie to, czego chcę. Jedyne, co chcę zmienić, to lista uczestników do posortowania według nazwiska. Próbowałem powiedzieć coś takiego:
{% for event in events %}
{{ event.location }}
{% for attendee in event.attendee_set.order_by__last_name %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
Niestety, powyższa składnia nie działa (tworzy pustą listę), podobnie jak żadna inna odmiana, o której myślałem (zgłoszono wiele błędów składniowych, ale bez radości).
Moim zdaniem mógłbym oczywiście stworzyć szereg posortowanych list uczestników, ale jest to brzydkie i kruche (i czy wspomniałem brzydkie) rozwiązanie.
Nie trzeba mówić, ale i tak powiem, przejrzałem dokumenty on-line i przeszukałem Stack Overflow oraz archiwa django-user, nie znajdując niczego pomocnego (ach, gdyby tylko zestaw zapytań był słownikiem, to dictsort zrobiłby praca, ale nie jest i nie działa)
==============================================
Zmieniono, aby dodać dodatkowe myśli po zaakceptowaniu odpowiedzi Tawmas.
Tawmas odniósł się do problemu dokładnie tak, jak go przedstawiłem - chociaż rozwiązanie nie było tym, czego się spodziewałem. W rezultacie nauczyłem się użytecznej techniki, którą można zastosować również w innych sytuacjach.
Odpowiedź Toma zaproponowała podejście, o którym wspomniałem już w moim OP i wstępnie odrzuciłem je jako „brzydkie”.
„Brzydka” była intuicyjną reakcją i chciałem wyjaśnić, co jest z nią nie tak. Robiąc to, zdałem sobie sprawę, że powodem, dla którego było to brzydkie podejście, było to, że ogarnął mnie pomysł przekazania zestawu zapytań do szablonu, który ma być renderowany. Jeśli złagodzę ten wymóg, istnieje brzydkie podejście, które powinno działać.
Nie próbowałem tego jeszcze, ale załóżmy, że zamiast przekazując queryset, kod widok powtórzyć przez zestaw zapytań produkujących listę zdarzeń, a następnie zdobione każde zdarzenie z zestawem zapytań do odpowiednich uczestników, który WAS posortowanych (lub sączy lub cokolwiek) w pożądany sposób. Coś takiego:
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)
Teraz szablon staje się:
{% for event in events %}
{{ event.location }}
{% for attendee in event.attendee_list %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
Wadą jest to, że pogląd musi „aktualizować” wszystkie zdarzenia naraz, co mogłoby stanowić problem, gdyby było ich dużo. Oczywiście można dodać paginację, ale to znacznie komplikuje widok.
Plusem jest to, że kod „przygotuj dane do wyświetlenia” jest w widoku, do którego należy, pozwalając szablonowi skupić się na formatowaniu danych dostarczonych przez widok do wyświetlenia. To jest słuszne i właściwe.
Dlatego planuję zastosować technikę Tawmasa do dużych stołów i powyższą technikę do małych stołów, z definicją dużego i małego pozostawionego czytelnikowi (uśmiech).
źródło
@property
jest to przesada, ponieważ nie ma tuMożesz użyć filtru szablonu dictsort https://docs.djangoproject.com/en/dev/ref/templates/builtins/#std:templatefilter-dictsort
To powinno działać:
{% for event in eventsCollection %} {{ event.location }} {% for attendee in event.attendee_set.all|dictsort:"last_name" %} {{ attendee.first_name }} {{ attendee.last_name }} {% endfor %} {% endfor %}
źródło
dictsortreversed
: docs.djangoproject.com/en/dev/ref/templates/builtins/ ...dictsort
pracowałem nad kodem prawie dokładnie takim, jak twój. Co ciekawe, wydaje się, że działa dobrze na zestawach zapytań.{% for attendee in event.attendee_set.all|dictsort:"last_name" %}
sortuje uczestników, ale{% for attendee in event.attendee_set.all | dictsort:"last_name" %}
próbuje posortować wyjście pętli for i przerywafor
.Jednym z rozwiązań jest utworzenie niestandardowego szablonu:
@register.filter def order_by(queryset, args): args = [x.strip() for x in args.split(',')] return queryset.order_by(*args)
użyj w ten sposób:
{% for image in instance.folder.files|order_by:"original_filename" %} ... {% endfor %}
źródło
przegrupowanie powinno być w stanie zrobić, co chcesz, ale czy istnieje powód, dla którego nie możesz zamówić ich tak, jak chcesz, z powrotem w widoku?
źródło