djangoテンプレートのカスタムテンプレートフィルターに複数の引数を追加するにはどうすればよいですか?


89

これが私のカスタムフィルターです:

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のドキュメントを調べましたが、1つの引数を使用した例しか見つかりませんでした...それも可能ですか?

回答:


108

それは可能で、かなり簡単です。

Djangoはフィルターに1つの引数しか許可しませんが、コンマを使用してすべての引数を1つの文字列にまとめることができない理由はありません。

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

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

これで、次のようなテンプレートタグを作成できます。

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(',')]

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

したがって、クエリ文字列と同様に、各パラメータは「&」で区切られます。

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

これで、置換関数は次のようになります。

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',''))

1
これらの値が変数にある場合、これを実装する方法...?
Anto 2013年

2
これは役に立ったように見えましたが、渡された変数で機能させることができませんでした。そのために、tagまたはsimple_tag-を使用しました。これにより、名前付き変数であっても、複数の変数を渡すことができます。
Furbeenator 2015年

18

ドキュメントのこのセクションによると不可能です:

カスタムフィルターは、1つまたは2つの引数を取るPython関数です。

  • 変数の値(入力)-必ずしも文字列である必要はありません。
  • 引数の値-これはデフォルト値を持つことも、完全に省略されることもあります。

ハードコードされた文字列を使用している場合、VanGaleのアプローチは機能します。Djangoチケット[ code.djangoproject.com/ticket/1199]は、カスタムフィルターで複数の引数をサポートし、パッチが受け入れられました。
ジェフバウアー

17

このように簡単です。

@register.filter(name='one_more')
def one_more(_1, _2):
    return _1, _2

def your_filter(_1_2, _3)
    _1, _2 = _1_2
    print "now you have three arguments, enjoy"

{{ _1|one_more:_2|your_filter:_3 }}

このソリューションを本当にありがとうございます。さまざまな長さのパラメーターをチェーンできるように、少しアップグレードしました。gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
フィリップDobrovolný

1
これは正解です!これは美しいPythonソリューションです(おそらく最高のdjangoソリューションではありません。@ dragonrootの回答を参照してください)
Antoine Draune

15

フィルタの代わりに、タグを単純なタグとして登録します。それらは複数の引数を取ることができます。それを呼び出すための構文は少し異なりますが、それは構文上の糖衣構文の変更にすぎません。


2
これが私の問題の正解でした。テンプレート変数をこの関数に渡すには、を使用する必要がありましたsimple_tag
Furbeenator 2015年

1
これは良い解決策です。単純なタグについては、djangoのドキュメントを確認する価値があります:docs.djangoproject.com/en/1.8/howto/custom-template-tags/…–
Gunther

6

思ったより簡単です 。これに

simple_tagを使用できます。

@register.simple_tag
def multiple_args_tag(a, b, c, d):
   #do your stuff
   return 

テンプレート内

{% multiple_args_tag 'arg1' 'arg2' 'arg3' 'arg4' %}

注:サーバーを再実行することを忘れないでください。


4

この機能は、2013 Django's TracでWONTFIXとしてマークされていますhttp://code.djangoproject.com/ticket/1199


そのチケットは昨年(2013年)WONTFIXとしてクローズされました。開発者は、複数の引数が必要な場合はカスタムタグを使用することを提案しています。
ポール・ロー

3

<my-site> /globaltags/replace.py

from django.template import Library

import re

register = Library()

def search(value, search):
    return re.sub(search, '#f4x@SgXXmS', value)

def replace(value, replace):
    return re.sub('#f4x@SgXXmS', replace, value)

register.filter(search)
register.filter(replace)

テンプレート内:

{{ "saniel"|search:"s"|replace:"d" }}

#f4x@SgXXmS少し説明していただけたら嬉しいですか?
ダンアブラモフ2011年

1
プレースホルダーとして使用される単なるランダムな文字列。この文字列は入力文字列の一部ではないと思ったので、この文字列を選択しました。たとえば、 '#f4x @SgXXmS'の代わりに "{}"を使用した場合{{"use {}代わりにoff []" | search: "off" | replace: "of"}}は次のようになります: "use of [] "の代わりに、期待される結果ではありません:" []の代わりに{}を使用してください "
theosp 2011年

5
ああ、それは理にかなっています。それをSUBSTRING_THAT_NEVER_OCCURS考えとして宣言するのはいいかもしれません。
ダンアブラモフ2011年

-1

あなたは単にこれを行うことができます:

{% assign find_total_issued = dailysalesreport | find: "TotalIssued":"13" %}

public static List<object> Find(object collection, string column, string value)

そして、関数の抽象化がであるため、宛先に到達しますsjare


-2

ここに悪い考えがありますが、機能します:

{{ xml|input_by_xpath:"{'type':'radio','xpath':'//result/value'}" }}

そして

@register.filter
def input_by_xpath(device, args): 
    args = eval(args)
    ...
    result = "<input type=\"%s\" value=\"%s\" name=\"%s\"/>"%(args['type'],value,args['xpath'])
    return mark_safe(result)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.