djangoテンプレートでクエリフィルタリングを実行するにはどうすればよいですか
-
03-07-2019 - |
質問
ビュー内のpythonコードに相当するオブジェクトのセットを取得するには、djangoテンプレート内からフィルターされたクエリを実行する必要があります:
queryset = Modelclass.objects.filter(somekey=foo)
テンプレートでやりたいこと
{% for object in data.somekey_set.FILTER %}
しかし、FILTERの書き方がわからないようです。
解決
これはできません。これは仕様です。 Djangoフレームワークの作成者は、プレゼンテーションコードをデータロジックから厳密に分離することを意図していました。モデルのフィルタリングはデータロジックであり、HTMLの出力はプレゼンテーションロジックです。
したがって、いくつかのオプションがあります。最も簡単な方法は、フィルタリングを実行し、結果をrender_to_response
に渡すことです。または、モデルにメソッドを記述して、{% for object in data.filtered_set %}
と言うことができます。最後に、独自のテンプレートタグを作成することもできますが、この特定のケースではそれに対してアドバイスします。
他のヒント
次のような追加のテンプレートタグを追加します。
@register.filter
def in_category(things, category):
return things.filter(category=category)
その後、次のことができます:
{% for category in categories %}
{% for thing in things|in_category:category %}
{{ thing }}
{% endfor %}
{% endfor %}
定期的にこの問題に遭遇し、しばしば<!> quot; add a method <!> quot;を使用します。溶液。ただし、<!> quot;メソッドの追加<!> quot;または<!> quot;ビューで計算<!> quot;動作しません(または動作しません)。例えば。テンプレートフラグメントをキャッシュしていて、それを作成するために重要なDB計算が必要な場合。必要な場合を除き、DBの作業を行いたくありませんが、テンプレートロジックを深く理解するまで、必要かどうかはわかりません。
他の可能な解決策:
-
{%expr <!> lt; expression <!> gt;を使用します<!> lt; var_name <!> gt; %} http://www.djangosnippets.org/snippets/9/ にあるテンプレートタグこの式は、ローカルスコープとしてテンプレートのコンテキストを使用する有効なPython式です。
-
テンプレートプロセッサを変更します。 Jinja2( http://jinja.pocoo.org/2/ )の構文は次とほぼ同じです。 Djangoテンプレート言語ですが、完全なPythonパワーが利用可能です。また、高速です。この卸売りを行うこともできますし、使用しているテンプレートに限定して使用することもできますが、Djangoの<!> quot; safer <!> quot;デザイナーが管理するページのテンプレート。
これは割り当てタグで解決できます:
from django import template
register = template.Library()
@register.assignment_tag
def query(qs, **kwargs):
""" template tag which allows queryset filtering. Usage:
{% query books author=author as mybooks %}
{% for book in mybooks %}
...
{% endfor %}
"""
return qs.filter(**kwargs)
他のオプションは、常に適用したいフィルターがある場合、問題のモデルのカスタムマネージャーは、返された結果に常にフィルターを適用します。
この良い例はEvent
モデルです。モデルで行うクエリの90%でEvent.objects.filter(date__gte=now)
のようなものが必要になります。つまり、通常はEvents
に興味があります今後の。これは次のようになります。
class EventManager(models.Manager):
def get_query_set(self):
now = datetime.now()
return super(EventManager,self).get_query_set().filter(date__gte=now)
そしてモデル内:
class Event(models.Model):
...
objects = EventManager()
しかし、これは<=>モデルで行われたすべてのデフォルトクエリに対して同じフィルターを適用するため、上記の手法の一部には柔軟性がありません。