从 jinja2 调用 Python 函数
- 2025-03-18 08:54:00
- admin 原创
- 43
问题描述:
我正在使用 jinja2,我想调用一个 python 函数作为辅助程序,使用类似于调用宏的语法。jinja2 似乎有意阻止我进行函数调用,并坚持让我通过将函数作为宏复制到模板中来重复自己。
有没有直接的方法可以做到这一点? 并且,有没有办法导入一整套 python 函数并让它们从 jinja2 访问,而无需经过大量的繁琐步骤(例如编写扩展)?
解决方案 1:
对于使用 Flask 的用户,请将其放入__init__.py
:
def clever_function():
return u'HELLO'
app.jinja_env.globals.update(clever_function=clever_function)
并在您的模板中调用它{{ clever_function() }}
解决方案 2:
注意:这是 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 %}
解决方案 3:
我认为 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
解决方案 4:
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 的答案
解决方案 5:
我喜欢@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__
!
解决方案 6:
从未在官方文档或 Stack Overflow 上看到过如此简单的方法,但是当我发现这个时我感到很惊讶:
# 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})
解决方案 7:
有一个更简单的决定。
@app.route('/x')
def x():
return render_template('test.html', foo=y)
def y(text):
return text
然后,在test.html中:
{{ foo('hi') }}
解决方案 8:
要从 Jinja2 调用 Python 函数,您可以使用与 类似的自定义过滤器globals
。
它非常简单实用。在文件 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)
解决方案 9:
使用 lambda 将模板连接到主代码
return render_template("clever_template", clever_function=lambda x: clever_function x)
然后就可以无缝调用模板中的函数了
{{clever_function(value)}}
解决方案 10:
有什么方法可以导入一整套 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 () }}
解决方案 11:
要导入所有内置函数,您可以使用:
app.jinja_env.globals.update(__builtins__)
如果这不起作用,.__dict__
请添加。__builtins__
根据John32323 的回答。
解决方案 12:
@John32323 的答案是一个非常干净的解决方案。
这是相同的,但保存到单独的文件中,可能更干净。
创建帮助文件
应用程序\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,
)
从应用程序导入
应用程序
from app import routes
from app import helper # add this one
像这样使用
应用程序\模板\some.html
{{ clever_function_1() }}
{{ clever_function_2(a, b) }}
解决方案 13:
对于使用 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() }}
解决方案 14:
如果你使用 Django 来执行此操作,则只需传递带有上下文的函数即可:
context = {
'title':'My title',
'str': str,
}
...
return render(request, 'index.html', context)
现在你将能够使用str
jinja2 模板中的函数
解决方案 15:
Creating a global function without passing to the template
@app.template_global('double')
def double(n):
return 2 * n
Jinja Usage`enter code here`
{{double(77)}}
Or
Creating a filter in jinja.
@app.template_filter('geo_stuff')
def hellome(a,b='dadadd'):
d=a+'it is jerry'
return d
jinja use
{{'foo'|geo_stuff}}
扫码咨询,免费领取项目管理大礼包!