Est-il possible de trier un ensemble d'éléments associés dans un modèle DJango?
C'est-à-dire: ce code (avec les balises HTML omises pour plus de clarté):
{% for event in eventsCollection %}
{{ event.location }}
{% for attendee in event.attendee_set.all %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
affiche presque exactement ce que je veux. La seule chose que je souhaite modifier est la liste des participants à trier par nom de famille. J'ai essayé de dire quelque chose comme ça:
{% for event in events %}
{{ event.location }}
{% for attendee in event.attendee_set.order_by__last_name %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
Hélas, la syntaxe ci-dessus ne fonctionne pas (elle produit une liste vide) et aucune autre variante à laquelle j'ai pensé (beaucoup d'erreurs de syntaxe signalées, mais pas de joie).
Je pourrais, bien sûr, produire une sorte de tableau de listes de participants triées à mon avis, mais c'est une solution laide et fragile (et ai-je mentionné laide).
Inutile de dire, mais je le dirai quand même, j'ai parcouru la documentation en ligne et recherché Stack Overflow et les archives de django-user sans rien trouver d'utile (ah, si seulement un ensemble de requêtes était un dictionnaire dictsort ferait le travail, mais ce n'est pas et ça ne marche pas)
==============================================
Modifié pour ajouter des pensées supplémentaires après avoir accepté la réponse de Tawmas.
Tawmas a abordé le problème exactement tel que je l'ai présenté - même si la solution n'était pas ce à quoi je m'attendais. En conséquence, j'ai appris une technique utile qui peut également être utilisée dans d'autres situations.
La réponse de Tom proposait une approche que j'avais déjà mentionnée dans mon OP et que j'avais provisoirement rejetée comme étant «moche».
Le "laid" était une réaction instinctive, et je voulais clarifier ce qui n'allait pas. Ce faisant, j'ai réalisé que la raison pour laquelle c'était une approche laide était que j'étais accroché à l'idée de transmettre un ensemble de requêtes au modèle à rendre. Si je relâche cette exigence, il y a une approche laide qui devrait fonctionner.
Je ne l' ai pas encore essayé, mais supposons que , plutôt que de passer le queryset, le code de la vue itérer à travers l'ensemble des requêtes produisant une liste d'événements, puis décoré chaque événement avec une série de requêtes pour les participants correspondants qui WAS triés (ou filtré, ou autre) de la manière souhaitée. Quelque chose comme ça:
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)
Maintenant, le modèle devient:
{% for event in events %}
{{ event.location }}
{% for attendee in event.attendee_list %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
L'inconvénient est que la vue doit «actualiser» tous les événements à la fois, ce qui pourrait être un problème s'il y avait un grand nombre d'événements. Bien sûr, on pourrait ajouter une pagination, mais cela complique considérablement la vue.
L'avantage est que le code "préparer les données à afficher" se trouve dans la vue à laquelle il appartient, ce qui permet au modèle de se concentrer sur le formatage des données fournies par la vue pour l'affichage. C'est juste et approprié.
Mon plan est donc d'utiliser la technique de Tawmas pour les grandes tables et la technique ci-dessus pour les petites tables, avec la définition du grand et du petit laissée au lecteur (sourire.)
la source
@property
sache, c'est exagéré ici car il n'y a pas de getters ou de setters impliqués: stackoverflow.com/questions/1554546/…Vous pouvez utiliser le filtre de modèle dictsort https://docs.djangoproject.com/en/dev/ref/templates/builtins/#std:templatefilter-dictsort
Cela devrait fonctionner:
{% for event in eventsCollection %} {{ event.location }} {% for attendee in event.attendee_set.all|dictsort:"last_name" %} {{ attendee.first_name }} {{ attendee.last_name }} {% endfor %} {% endfor %}
la source
dictsortreversed
: docs.djangoproject.com/en/dev/ref/templates/builtins/…dictsort
travaillé correctement sur du code presque exactement comme le vôtre. Fait intéressant, cela semble fonctionner correctement sur les ensembles de requêtes.{% for attendee in event.attendee_set.all|dictsort:"last_name" %}
trie les participants, mais{% for attendee in event.attendee_set.all | dictsort:"last_name" %}
tente de trier la sortie de la boucle for et interrompt lefor
.Une solution consiste à créer un gabarit personnalisé:
@register.filter def order_by(queryset, args): args = [x.strip() for x in args.split(',')] return queryset.order_by(*args)
utiliser comme ceci:
{% for image in instance.folder.files|order_by:"original_filename" %} ... {% endfor %}
la source
regroup devrait être en mesure de faire ce que vous voulez, mais y a-t-il une raison pour laquelle vous ne pouvez pas les réorganiser comme vous le souhaitez dans la vue?
la source