从jinja2调用python函数

Lee*_*Lee 130 python jinja2

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

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

小智 203

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

def clever_function():
    return u'HELLO'

app.jinja_env.globals.update(clever_function=clever_function)
Run Code Online (Sandbox Code Playgroud)

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

  • 现在,flask.app 有一个装饰器:`@app.template_global(name)`。https://flask.palletsprojects.com/en/2.0.x/api/#flask.Flask.template_global https://github.com/pallets/flask/blob/7a73171edc3bcffef96ef6367977ab3ae9af9350/src/flask/app.py#L1177 (4认同)
  • 在较新的版本(我使用Jinja2 2.9.6)它似乎更容易工作.使用函数就像使用变量一样(在更复杂的情况下也适用):`from jinja2 import Template ## newline ## def clever_function():## newline ## return"Hello"## newline ## template = Template ("{{clever_function()}}")## newline ## print(template.render(clever_function = clever_function))` (3认同)
  • 即使 8 年后,如果您使用 Flask,这似乎是比任何最新答案更干净的解决方案。回答 @ffghfgh 的老问题,是的,您可以传递多个函数。 (2认同)

Lia*_*ley 117

注意:这是特定于Flask的!

我知道这篇文章很老了,但是有更好的方法可以在较新版本的Flask中使用上下文处理器.

可以轻松创建变量:

@app.context_processor
def example():
    return dict(myexample='This is an example')
Run Code Online (Sandbox Code Playgroud)

以上内容可以在带有Flask的Jinja2模板中使用,如下所示:

{{ myexample }}
Run Code Online (Sandbox Code Playgroud)

(哪个输出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)
Run Code Online (Sandbox Code Playgroud)

以上使用时如下:

{{ format_price(0.33) }}
Run Code Online (Sandbox Code Playgroud)

(使用货币符号输出输入价格)

或者,您可以使用烘焙到Flask中的jinja过滤器.例如使用装饰器:

@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]
Run Code Online (Sandbox Code Playgroud)

或者,没有装饰器,并手动注册该功能:

def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter
Run Code Online (Sandbox Code Playgroud)

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

{% for x in mylist | reverse %}
{% endfor %}
Run Code Online (Sandbox Code Playgroud)

  • @AJP理论上还是回答了这个问题.这是解决问题的唯一方法,因为您也使用Flask.有点像所有JavaScript问题经常回答有或没有jQuery的替代方案或Python的问题经常回答Python2和3.问题不是排除Flask.(不像关于Py2的问题会排除Py3答案).这个答案对我有帮助. (13认同)
  • 唐被投票询问有关Jinja2的问题,答案是Flask特有的. (5认同)
  • 应该在哪里存在这些函数,init,views还是其他任何地方? (3认同)
  • `__init __.py`假设您在那里声明了`flask.Flask(__ name __)`. (3认同)
  • 非常有帮助,而且正是我想要的。Jinja2是Web框架的一部分,因此并不完全独立于后端。我在Django和Flask中都使用Python工作,本文以及其他与我相关的文章。在我看来,试图过度指定问题与不必要地含糊其辞一样有害。 (2认同)

Rob*_*wie 73

我认为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
Run Code Online (Sandbox Code Playgroud)

  • 我也发现了这一点 - 您可以使用以下内容添加模块:`import utils.helpers env.globals ['helpers'] = utils.helpers` (3认同)
  • 因此,`{{ smart_function('a', 'b') }}` (3认同)

AJP*_*AJP 40

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
Run Code Online (Sandbox Code Playgroud)

将输出:

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

适用于Jinja2版本2.7.3

  • @BorkoKovacev这不是一个好理由.我只投了2个答案; 答案是关于Flask而不是Jinja2.如果他们想要编辑他们的主题和关于Jinja2的答案,我会投票给他们. (13认同)
  • 可能是因为你贬低了其他人的答案:( (8认同)
  • 我相信你是正确的. (5认同)
  • 我制作了这个答案的函数装饰器版本。目前它处于底部,有 0 票:,-( /sf/answers/3310376821/ (2认同)
  • @BrunoBronosky 不错。已经投票:) ...再给它十年,它可能比我的高:P ...虽然永远不会赶上烧瓶;P (2认同)

Bru*_*sky 21

我喜欢@ 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))
Run Code Online (Sandbox Code Playgroud)

好东西有一个功能__name__!


Mat*_*kin 12

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

# 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})
Run Code Online (Sandbox Code Playgroud)


Rob*_*low 8

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

return render_template("clever_template", clever_function=lambda x: clever_function x)
Run Code Online (Sandbox Code Playgroud)

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

{{clever_function(value)}}
Run Code Online (Sandbox Code Playgroud)

  • @odiumediae:不,不是.这完全没必要.只需传递函数句柄本身:clever_function = clever_function (21认同)

小智 8

还有一个更简单的决定。

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

def y(text):
    return text
Run Code Online (Sandbox Code Playgroud)

然后,在test.html 中

{{ foo('hi') }}
Run Code Online (Sandbox Code Playgroud)


小智 5

要从Jinja2调用python函数,可以使用与全局变量相似的自定义过滤器:http : //jinja.pocoo.org/docs/dev/api/#writing-filters

这非常简单和有用。在文件myTemplate.txt中,我写道:

{{ data|pythonFct }}
Run Code Online (Sandbox Code Playgroud)

并在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)
Run Code Online (Sandbox Code Playgroud)


Kud*_*nle 5

有什么方法可以导入一整套 python 函数并可以从 jinja2 访问它们吗?

是的,除了上面的其他答案外,这对我有用。

创建一个类并使用相关的方法填充它,例如

class Test_jinja_object:

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

    def clever_function (self):
        return 'hello' 
Run Code Online (Sandbox Code Playgroud)

然后在视图函数中创建类的实例,并将结果对象作为 render_template 函数的参数传递给模板

my_obj = Test_jinja_object()
Run Code Online (Sandbox Code Playgroud)

现在在您的模板中,您可以像这样调用 jinja 中的类方法

{{ my_obj.clever_function () }}
Run Code Online (Sandbox Code Playgroud)


Sol*_*cko 5

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

app.jinja_env.globals.update(__builtins__)
Run Code Online (Sandbox Code Playgroud)

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

基于John32323 的回答