1. ホーム
  2. django

[解決済み] django テンプレートで、カスタムテンプレートフィルタに複数の引数を追加するには?

2023-01-15 01:34:29

質問

私のカスタムフィルタです。

from django import template

register = template.Library()

@register.filter
def replace(value, cherche, remplacement):
    return value.replace(cherche, remplacement)

と、テンプレートファイルで使ってみて、エラーになった方法を紹介します。

{{ attr.name|replace:"_"," " }}
{{ attr.name|replace:"_" " " }}
{{ attr.name|replace:"_":" " }}
{{ attr.name|replace:"cherche='_', remplacement=' '" }}

を調べてみると django のドキュメント 書籍 が、単一の引数を使用する例しか見つかりませんでした...それは可能なのでしょうか?

どのように解決するのですか?

可能です。

Django はフィルタの引数を一つしか許しませんが、すべての引数をカンマで区切って一つの文字列にすることができない理由はありません。

ですから、例えば、変数 X がリスト [1,2,3,4] の中にあるかどうかをチェックするフィルタが欲しい場合、次のようなテンプレートフィルタが必要になります。

{% if X|is_in:"1,2,3,4" %}

さて、このようにtemplatetagを作成します。

from django.template import Library

register = Library()

def is_in(var, args):
    if args is None:
        return False
    arg_list = [arg.strip() for arg in args.split(',')]
    return var in arg_list

register.filter(is_in)

arg_listを作成している行は、args文字列をすべてのカンマで分割し、.strip()を呼び出して先頭と末尾のスペースを除去するジェネレータ式です。

例えば、第3引数がintであれば、そのまま実行します。

arg_list[2] = int(arg_list[2])

あるいは、全部がint型ならそうする。

arg_list = [int(arg) for arg in args.split(',')]

EDIT: さて、パラメータとしてキーと値のペアを使うことであなたの質問に具体的に答えますと、Django が URL からクエリ文字列をパースするのに使うのと同じクラスを使うことができ、これは settings.py に従って適切に文字エンコーディングを処理する利点も持っています。

つまり、クエリ文字列と同じように、各パラメータは '&' で区切られます。

{{ attr.name|replace:"cherche=_&remplacement= " }}

すると、replace関数は次のようになります。

from django import template
from django.http import QueryDict

register = template.Library()

@register.filter
def replace(value, args):
    qs = QueryDict(args)
    if qs.has_key('cherche') and qs.has_key('remplacement'):
        return value.replace(qs['cherche'], qs['remplacement'])
    else:
        return value

間違った置換を行うリスクを冒してでも、これをいくらか高速化することができます。

qs = QueryDict(args)
return value.replace(qs.get('cherche',''), qs.get('remplacement',''))