web-dev-qa-db-ja.com

jinja2からpython関数を呼び出す

私はjinja2を使用していますが、マクロを呼び出す場合と同様の構文を使用して、ヘルパーとしてpython関数を呼び出したいと思います。 jinja2は、関数呼び出しができないようにすることを意図しているようで、マクロとして関数をテンプレートにコピーすることで繰り返します。

これを行う簡単な方法はありますか?そして、python関数のセット全体をインポートし、多くのリガマロールを行わずに(拡張機能の作成など)、それらをjinja2からアクセスできるようにする方法はありますか?

124
Lee

Flaskを使用している場合は、これを__init__.pyに入れてください:

def clever_function():
    return u'HELLO'

app.jinja_env.globals.update(clever_function=clever_function)

そしてあなたのテンプレートで{{ clever_function() }}でそれを呼び出します

199
John32323

注:これはFlask固有です!

この投稿はかなり古いものですが、コンテキストプロセッサを使用してFlaskの新しいバージョンでこれを行うより良い方法があります。

変数は簡単に作成できます:

@app.context_processor
def example():
    return dict(myexample='This is an example')

上記は、次のようにFlaskを含むJinja2テンプレートで使用できます。

{{ myexample }}

This is an exampleを出力します)

および本格的な機能:

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u'€'):
        return u'{0:.2f}{1}'.format(amount, currency)
    return dict(format_price=format_price)

上記のように使用した場合:

{{ format_price(0.33) }}

(通貨記号で入力価格を出力します)

別の方法として、 jinja filters を使用して、Flaskにベイクできます。例えば。デコレータの使用:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

または、デコレータなしで、関数を手動で登録します。

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

上記の2つの方法で適用されたフィルターは、次のように使用できます。

{% for x in mylist | reverse %}
{% endfor %}
111
Liam Stanley
from jinja2 import Template

def custom_function(a):
    return a.replace('o', 'ay')

template = Template('Hey, my name is {{ custom_function(first_name) }} {{ func2(last_name) }}')
template.globals['custom_function'] = custom_function

Matroskin's answer に従ってフィールドに関数を与えることもできます

fields = {'first_name': 'Jo', 'last_name': 'Ko', 'func2': custom_function}
print template.render(**fields)

出力されます:

Hey, my name is Jay Kay

Jinja2バージョン2.7.3で動作

また、デコレータでtemplate.globalsの関数の定義を簡単にしたい場合は、チェックアウト Bruno Bronosky's answer

38
AJP

@ AJP's answer が好きです。たくさんの機能ができるまで、そのまま使いました。それから Python関数デコレータ に切り替えました。

from jinja2 import Template

template = '''
Hi, my name is {{ custom_function1(first_name) }}
My name is {{ custom_function2(first_name) }}
My name is {{ custom_function3(first_name) }}
'''
jinga_html_template = Template(template)

def template_function(func):
    jinga_html_template.globals[func.__name__] = func
    return func

@template_function
def custom_function1(a):
    return a.replace('o', 'ay')

@template_function
def custom_function2(a):
    return a.replace('o', 'ill')

@template_function
def custom_function3(a):
    return 'Slim Shady'

fields = {'first_name': 'Jo'}
print(jinga_html_template.render(**fields))

良い機能には__name__があります!

17
Bruno Bronosky

公式ドキュメントやスタックオーバーフローでこのような簡単な方法を見たことはありませんが、これを見つけたときは驚きました:

# jinja2.__version__ == 2.8
from jinja2 import Template

def calcName(n, i):
    return ' '.join([n] * i)

template = Template("Hello {{ calcName('Gandalf', 2) }}")

template.render(calcName=calcName)
# or
template.render({'calcName': calcName})
11
Matroskin

ラムダを使用して、テンプレートをメインコードに接続します

return render_template("clever_template", clever_function=lambda x: clever_function x)

その後、テンプレート内の関数をシームレスに呼び出すことができます

{{clever_function(value)}}
9
Robert Onslow

Jinja2からpython関数を呼び出すには、グローバルと同様に機能するカスタムフィルターを使用できます。 http://jinja.pocoo.org/docs/dev/api/#writing-filters

とてもシンプルで便利です。 myTemplate.txtファイルに次のように書きました。

{{ data|pythonFct }}

pythonスクリプト内:

import jinja2

def pythonFct(data):
    return "This is my data: {0}".format(data)

input="my custom filter works!"

loader = jinja2.FileSystemLoader(path or './')
env = jinja2.Environment(loader=loader)
env.filters['pythonFct'] = pythonFct
result = env.get_template("myTemplate.txt").render(data=input)
print(result)
5
Ben9000RPM

python関数のセット全体をインポートし、jinja2からアクセスできるようにする方法はありますか?

はい、あります、上記の他の答えに加えて、これは私のために働きます。

クラスを作成し、それに関連するメソッドを設定します。

class Test_jinja_object:

    def __init__(self):
        self.myvar = 'sample_var'

    def clever_function (self):
        return 'hello' 

次に、ビュー関数でクラスのインスタンスを作成し、結果のオブジェクトをrender_template関数のパラメーターとしてテンプレートに渡します

my_obj = Test_jinja_object()

テンプレートで、次のようにjinjaのクラスメソッドを呼び出すことができます

{{ my_obj.clever_function () }}

すべての組み込み関数をインポートするには、次を使用できます。

app.jinja_env.globals.update(__builtins__)

これが機能しない場合は、.__dict__の後に__builtins__を追加します。

John32323の回答 に基づきます。

3
Solomon Ucko

Djangoで実行している場合は、コンテキストで関数を渡すことができます。

context = {
    'title':'My title',
    'str': str,
}
...
return render(request, 'index.html', context)

これで、jinja2テンプレートでstr関数を使用できるようになります。

2
Jahid