web-dev-qa-db-ja.com

Djangoテンプレートで関連アイテムをソートする

Djangoテンプレートで関連アイテムのセットをソートすることは可能ですか?

つまり、このコード(わかりやすくするためにHTMLタグは省略されています):

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

almostまさに欲しい変更したいのは、出席者のリストを姓でソートすることだけです。私はこのようなことを言ってみました:

{% 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のアーカイブを検索しました。仕事ですが、そうではなく、そうではありません)

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

Tawmasの回答を受け入れた後、さらに考えを追加するために編集されました。


Tawmasは私が提示したとおりに問題に対処しましたが、解決策は私が期待したものではありませんでした。その結果、他の状況でも使用できる便利なテクニックを学びました。

トムの答えは、私がすでにOPで言及したアプローチを提案し、「 "い」として暫定的に拒否しました。

「ugい」は直感的な反応であり、何が悪いのかを明確にしたかったのです。そうすることで、それがapproachいアプローチである理由は、レンダリングするテンプレートにクエリセットを渡すという考えに固執したためだと気づきました。その要件を緩和すると、動作するはずの見苦しいアプローチがあります。

私はまだこれを試していませんが、クエリセットを渡すのではなく、ビューコードがクエリセットを反復処理してイベントのリストを生成し、各イベントを対応する出席者のクエリセットで装飾したと仮定します[〜#〜]は、[〜#〜]希望の方法でソート(またはフィルター処理など)されていました。そのようなもの:

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の手法を使用し、小さなテーブルには上記の手法を使用し、大小の定義は読者に任せています(笑)。

75
Dale Wilson

このように、出席者モデルで順序を指定する必要があります。例(モデルクラスの名前がAttendeeであると仮定):

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

詳細については、 マニュアル を参照してください。

[〜#〜] edit [〜#〜]。別の解決策は、イベントモデルにプロパティを追加し、テンプレートからアクセスできるようにすることです。

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

必要に応じてこれらをさらに定義できます...

116
tawmas

テンプレートフィルターを使用できますdictsorthttps://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 %}
103
tariwan

regroup はあなたが望むことをすることができるはずですが、ビューであなたが望む方法でそれらを注文できない理由はありますか?

0
Tom

1つの解決策は、カスタムテンプレートを作成することです。

@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
matinfo