问题:从jinja2调用python函数
我正在使用jinja2,并且想使用类似于调用宏的语法来调用python函数作为辅助函数。jinja2似乎旨在阻止我进行函数调用,并坚持要通过将函数复制到模板中作为宏来重复我自己。
有没有简单的方法可以做到这一点?而且,有没有什么方法可以导入整套python函数并使它们从jinja2中进行访问,而无需经历大量的rigamarole(例如编写扩展名)?
回答 0
对于使用Flask的用户,请将其放入您的__init__.py
:
def clever_function():
return u'HELLO'
app.jinja_env.globals.update(clever_function=clever_function)
然后在您的模板中调用 {{ clever_function() }}
回答 1
注意:这是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) }}
(输出带有货币符号的输入价格)
另外,您也可以使用Flask中的jinja过滤器。例如使用装饰器:
@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
我认为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
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的答案在字段中提供功能
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的答案
回答 4
我喜欢@AJP的答案。我逐字使用它,直到获得了很多功能。然后我切换到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__
!
回答 5
从来没有在官方文档或堆栈溢出中看到过如此简单的方法,但是当我发现这一点时,我感到惊讶:
# 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
使用Lambda将模板连接到您的主代码
return render_template("clever_template", clever_function=lambda x: clever_function x)
然后,您可以无缝调用模板中的函数
{{clever_function(value)}}
回答 7
要从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)
回答 8
有什么方法可以导入整套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
要导入所有内置函数,可以使用:
app.jinja_env.globals.update(__builtins__)
如果这不起作用,请.__dict__
在之后添加__builtins__
。
基于John32323的答案。
回答 10
如果使用Django,则只需将函数与上下文一起传递即可:
context = {
'title':'My title',
'str': str,
}
...
return render(request, 'index.html', context)
现在您将能够使用str
jinja2模板中的功能
回答 11
有一个更简单的决定。
@app.route('/x')
def x():
return render_template('test.html', foo=y)
def y(text):
return text
然后,在test.html中:
{{ y('hi') }}