É possível classificar um conjunto de itens relacionados em um modelo DJango?
Isto é: este código (com tags HTML omitidas para maior clareza):
{% for event in eventsCollection %}
{{ event.location }}
{% for attendee in event.attendee_set.all %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
exibe quase exatamente o que eu quero. A única coisa que quero mudar é que a lista de participantes seja classificada pelo sobrenome. Tentei dizer algo assim:
{% for event in events %}
{{ event.location }}
{% for attendee in event.attendee_set.order_by__last_name %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
Infelizmente, a sintaxe acima não funciona (ela produz uma lista vazia) e nem qualquer outra variação que eu tenha pensado (muitos erros de sintaxe relatados, mas nenhum prazer).
Eu poderia, é claro, produzir algum tipo de conjunto de listas classificadas de participantes, na minha opinião, mas essa é uma solução feia e frágil (e já mencionei feia).
Desnecessário dizer, mas direi mesmo assim, eu li os documentos on-line e pesquisei Stack Overflow e os arquivos do django-user sem encontrar nada útil (ah, se apenas um conjunto de consulta fosse um dicionário dictsort faria o trabalho, mas não é e não faz)
==================================================
Editado para adicionar pensamentos adicionais após aceitar a resposta de Tawmas.
Tawmas abordou o problema exatamente como eu apresentei - embora a solução não fosse o que eu esperava. Como resultado, aprendi uma técnica útil que também pode ser usada em outras situações.
A resposta de Tom propôs uma abordagem que já havia mencionado em meu OP e rejeitei provisoriamente como sendo "feia".
O "feio" foi uma reação instintiva, e eu queria esclarecer o que havia de errado com ele. Ao fazer isso, percebi que a razão pela qual era uma abordagem feia era porque estava preso à ideia de passar um conjunto de consultas para o modelo a ser processado. Se eu relaxar essa exigência, há uma abordagem desagradável que deve funcionar.
Eu não tentei isso ainda, mas suponha que ao invés de passar o queryset, o código vista iterado através do conjunto de consulta produzindo uma lista de eventos, em seguida, decorado cada evento com um conjunto de consulta para os participantes correspondentes que FOI ordenados (ou filtrada, ou qualquer outra coisa) da maneira desejada. Algo assim:
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)
Agora o modelo se torna:
{% for event in events %}
{{ event.location }}
{% for attendee in event.attendee_list %}
{{ attendee.first_name }} {{ attendee.last_name }}
{% endfor %}
{% endfor %}
A desvantagem é que a visão precisa "atualizar" todos os eventos de uma vez, o que poderia ser um problema se houvesse um grande número de eventos. Claro que pode-se adicionar paginação, mas isso complica consideravelmente a visão.
A vantagem é que o código "preparar os dados a serem exibidos" está na visualização a que pertence, permitindo que o modelo se concentre na formatação dos dados fornecidos pela visualização para exibição. Isso é certo e adequado.
Portanto, meu plano é usar a técnica de Tawmas para tabelas grandes e a técnica acima para tabelas pequenas, com a definição de grande e pequeno deixada para o leitor (sorriso.)
fonte
@property
é um exagero aqui, já que não há getters ou setters envolvidos: stackoverflow.com/questions/1554546/…Você pode usar o filtro de modelo dictsort https://docs.djangoproject.com/en/dev/ref/templates/builtins/#std:templatefilter-dictsort
Isso deve funcionar:
{% for event in eventsCollection %} {{ event.location }} {% for attendee in event.attendee_set.all|dictsort:"last_name" %} {{ attendee.first_name }} {{ attendee.last_name }} {% endfor %} {% endfor %}
fonte
dictsortreversed
: docs.djangoproject.com/en/dev/ref/templates/builtins/…dictsort
trabalhando corretamente em um código quase igual ao seu. Curiosamente, parece funcionar bem em querysets.{% for attendee in event.attendee_set.all|dictsort:"last_name" %}
classifica os participantes, mas{% for attendee in event.attendee_set.all | dictsort:"last_name" %}
tenta classificar a saída do loop for e interrompe ofor
.Uma solução é fazer um templatag personalizado:
@register.filter def order_by(queryset, args): args = [x.strip() for x in args.split(',')] return queryset.order_by(*args)
use assim:
{% for image in instance.folder.files|order_by:"original_filename" %} ... {% endfor %}
fonte
O reagrupamento deve ser capaz de fazer o que você deseja, mas há um motivo pelo qual você não pode ordená-los da maneira que deseja de volta na exibição?
fonte