从jinja2调用python函数
我正在使用jinja2,我想调用一个python函数作为助手,使用类似的语法,如果我正在调用一个macros。 jinja2似乎意图阻止我进行一个函数调用,并坚持我通过将函数复制到模板中作为一个macros来重复自己。
有没有简单的方法来做到这一点? 而且,还有什么办法可以导入一整套python函数,并且可以通过jinja2访问它们,而不需要经过大量的细节(如编写扩展名)?
对于那些使用Flask的人,把它放在你的__init__.py
:
def clever_function(): return u'HELLO' app.jinja_env.globals.update(clever_function=clever_function)
并在你的模板中调用{{ clever_function() }}
注意:这是特定的瓶子!
我知道这个post是相当古老的,但有更好的方法在使用上下文处理器的更新版本的Flask中执行此操作。
variables可以很容易地创build:
@app.context_processor def example(): return dict(myexample='This is an example')
以上可以在Flask中使用Jinja2模板,如下所示:
{{ myexample }}
(哪个输出This is an example
)
以及完整的function:
@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) }}
(输出货币符号的input价格)
或者,你可以使用忍者filter ,烧成烧瓶。 比如使用装饰器:
@app.template_filter('reverse') def reverse_filter(s): return s[::-1]
或者,没有装饰器,并手动注册function:
def reverse_filter(s): return s[::-1] app.jinja_env.filters['reverse'] = reverse_filter
以上两种方法应用的filter可以这样使用:
{% for x in mylist | reverse %} {% endfor %}
我认为jinja故意让模板内运行“任意”python变得困难。 它试图强化模板中较less的逻辑是好事的观点。
您可以在一个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
from jinja2 import Template def custom_function(a): return a.replace('o', 'ay') template = 'Hey, my name is {{ custom_function(first_name) }}' jinga_html_template = Template(template) jinga_html_template.globals['custom_function'] = custom_function fields = {'first_name': 'Jo'} print jinga_html_template.render(**fields)
会输出:
Hey, my name is Jay
适用于Jinja2版本2.7.3
使用lambda将模板连接到主代码
return render_template("clever_template", clever_function=lambda x: clever_function x)
然后,您可以无缝地调用模板中的function
{{clever_function(value)}}
从来没有在官方文档或堆栈溢出看到这样简单的方式,但是当我发现这一点时,我感到惊讶:
# 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})
要从Jinja2中调用一个python函数,你可以使用自定义filter,这些filter和全局variables一样: 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)
如果你正在使用Django,你可以通过上下文来传递函数:
context = { 'title':'My title', 'str': str, } ... return render(request, 'index.html', context)
现在你将能够在jinja2模板中使用str
函数
有没有办法导入一整套python函数,并让他们从jinja2访问?
是的,除了上面的其他答案,这对我有用。
创build一个类并使用关联的方法填充它,例如
class Test_jinja_object: def __init__(self): self.myvar = 'sample_var' def clever_function (self): return 'hello'
然后在你的视图函数中创build你的类的一个实例,并将结果对象作为render_template函数的parameter passing给你的模板
my_obj = Test_jinja_object()
现在在你的模板中,你可以像这样调用jinja中的类方法
{{ my_obj.clever_function () }}
我喜欢@ AJP的回答 。 我逐字地使用它,直到我结束了很多function。 然后我切换到一个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 def func_wrapper(*args, **kwargs): return func(*args, **kwargs) return func_wrapper @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__
!