从jinja2调用python函数

时间:2011-05-17 19:29:49

标签: python jinja2

我正在使用jinja2,我想调用一个python函数作为帮助器,使用类似的语法,就像我调用一个宏一样。 jinja2似乎打算阻止我进行函数调用,并坚持通过将函数作为宏复制到模板中来重复自己。

有没有直接的方法来做到这一点?并且,有没有办法导入一整套python函数,并可以从jinja2访问它们,而无需经过大量的繁琐工作(例如编写扩展)?

14 个答案:

答案 0 :(得分:194)

对于那些使用Flask的人,请将其放在__init__.py

def clever_function():
    return u'HELLO'

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

并在模板中使用{{ clever_function() }}

进行调用

答案 1 :(得分:108)

注意:这是特定于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

使用上述两种方法应用的过滤器可以这样使用:

{% for x in mylist | reverse %}
{% endfor %}

答案 2 :(得分:70)

我认为jinja故意难以在模板中运行'任意'python。它试图强化这样的观点,即模板中较少的逻辑是一件好事。

您可以在Environment实例中操作全局命名空间以添加对函数的引用。必须在之前完成加载任何模板。例如:

from jinja2 import Environment, FileSystemLoader

def clever_function(a, b):
    return u''.join([b, a])

env = Environment(loader=FileSystemLoader('/path/to/templates'))
env.globals['clever_function'] = clever_function

答案 3 :(得分:36)

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

答案 4 :(得分:12)

我喜欢@AJP's answer。我逐字地使用它,直到我结束了很多功能。然后我切换到Python function decorator

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__

答案 5 :(得分:10)

从未在官方文档或堆栈溢出中看到这么简单的方法,但是当发现这个时我很惊讶:

# 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})

答案 6 :(得分:9)

使用lambda将模板连接到主代码

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

然后您可以无缝地调用模板中的函数

{{clever_function(value)}}

答案 7 :(得分:4)

要从Jinja2调用python函数,您可以使用与globals类似的自定义过滤器: 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)

答案 8 :(得分:2)

有没有办法导入一整套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 () }}

答案 9 :(得分:2)

要导入您可以使用的所有内置函数:

app.jinja_env.globals.update(__builtins__)

如果这不起作用,请在.__dict__之后添加__builtins__

基于John32323's answer

答案 10 :(得分:2)

有一个简单得多的决定。

@app.route('/x')
def x():
    return render_template('test.html', foo=y)

def y(text):
    return text

然后,在 test.html 中:

{{ foo('hi') }}

答案 11 :(得分:1)

如果你正在使用Django,你可以通过上下文传递函数:

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

现在,您将能够使用jinja2模板中的str功能

答案 12 :(得分:0)

@ John32323的答案是一个非常干净的解决方案。

这里是同一个人,但是保存到一个单独的文件中,也许更干净。

创建帮助文件

app \ helper.py

from app import app

def clever_function_1():
    return u'HELLO'

def clever_function_2(a, b):
    return a + b



app.jinja_env.globals.update(
    clever_function_1=clever_function_1,
    clever_function_2=clever_function_2,
)

从应用程序导入

app.py

from app import routes
from app import helper   # add this one

像这样使用

app \ templates \ some.html


{{ clever_function_1() }}
{{ clever_function_2(a, b) }}

答案 13 :(得分:0)

对于那些使用 FastApi 的人,请将其放在您的 __init__.py 中:

from fastapi.templating import Jinja2Templates
templates = Jinja2Templates(directory="templates")

def clever_function():
    return u'HELLO'

templates.env.globals.update(clever_function=clever_function)

并在您的模板中使用 {{ clever_function() }}

调用它