web-dev-qa-db-ja.com

Djangoテンプレートでクエリフィルタリングを実行する方法

ビュー内のDjangoコードに相当するオブジェクトのセットを取得するには、python=テンプレートからフィルター処理されたクエリを実行する必要があります。

queryset = Modelclass.objects.filter(somekey=foo)

私のテンプレートでやりたいこと

{% for object in data.somekey_set.FILTER %}

しかし、FILTERの書き方がわからないようです。

73
Ber

これはできません。これは仕様です。 Djangoフレームワークの作成者は、プレゼンテーションコードとデータロジックを厳密に分離することを意図していました。

そのため、いくつかのオプションがあります。最も簡単な方法は、フィルタリングを実行してから、結果をrender_to_responseに渡すことです。または、モデルにメソッドを記述して、{% for object in data.filtered_set %}と言うことができます。最後に、独自のテンプレートタグを作成することもできますが、この特定のケースではそれに対してアドバイスします。

112
Eli Courtwright

次のようなテンプレートタグを追加します。

@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 %}
29
tobych

私はこの問題に定期的に遭遇し、しばしば「メソッドの追加」ソリューションを使用します。ただし、「メソッドの追加」または「ビューでの計算」が機能しない(またはうまく機能しない)場合があります。例えば。テンプレートフラグメントをキャッシュしていて、それを作成するために重要なDB計算が必要な場合。必要な場合を除き、DBの作業を行いたくありませんが、テンプレートロジックを深く理解するまで、必要かどうかはわかりません。

他の可能な解決策:

  1. http://www.djangosnippets.org/snippets/9/ にある{%expr <expression> as <var_name>%}テンプレートタグを使用します。式は任意の有効なPythonローカルスコープとしてテンプレートのコンテキストを使用した式。

  2. テンプレートプロセッサを変更します。 Jinja2( http://jinja.pocoo.org/2/ )は、Djangoテンプレート言語とほぼ同じですが、完全なPython電力が利用可能です。これも高速です。この卸売りを行うことも、youが取り組んでいるテンプレートに使用を制限することもできます。 、ただし、デザイナーが管理するページにはDjangoの「安全な」テンプレートを使用します。

11
Peter Rowell

これは、割り当てタグで解決できます。

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)
9
chrisv

もう1つのオプションは、常に適用したいフィルターがある場合、問題のモデルに カスタムマネージャー を追加し、返された結果に常にフィルターを適用することです。

この良い例は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()

しかし、これもEventモデルで行われたすべてのデフォルトクエリに対して同じフィルターを適用するため、上記の手法の一部には柔軟性がありません。

8
mrmagooey