Jinja2模板中的"eval"语句

4

我正在尝试将一些旧的Smarty模板转换为Jinja2。

Smarty在模板中使用eval语句从当前上下文渲染一个模板字符串。

Jinja2中是否有类似于eval的等效功能?或者有什么好的解决方法?

4个回答

1
使用@jinja2.contextfilter装饰器创建一个自定义过滤器以渲染变量:
from flask import render_template_string
from jinja2 import contextfilter
from markupsafe import Markup


@contextfilter
def dangerous_render(context, value):
    Markup(render_template_string(value, **context)).format()

然后在你的 template.html 文件中:
{{ myvar|dangerous_render }}

Markup(...) 上的 render() 方法对我无效,我认为它没有这个方法。 - Andreas Maier
@AndreasMaier 谢谢,已更新以适配最新的Flask、Jinja2和markupsafe。 - Alan Hamlett

1
根据Alan Hamlett和Hilario Nengare的答案,我为Jinja2(>=3.0)实现了以下的"eval"过滤器。我发现应该还要处理未定义输入的情况,并且我还添加了指定额外变量作为表达式输入的功能。
import jinja2

@jinja2.pass_context
def filter_eval(context, input, **vars):
    if input == jinja2.Undefined:
        return input
    return jinja2.Template(input).render(context, **vars)

使用时,将filter_eval()作为"eval"过滤器添加:

  • 模板源代码:

    {% set rack_str = 'Rack {{ rack }}' %}
    {{ rack_str | eval(rack='A') }}
    
  • 渲染后的模板:

    Rack A
    

0
我正在寻找类似的eval用例,并偶然发现了不同的stackoverflow帖子。
这对我有用。

routes.py

def index():
    html = "<b>actual eval string</b>"
    return render_template('index.html', html_str = html)

index.html

<html>
    <head>
        <title>eval jinja</title>
    </head>
    <body>
        {{ html_str | safe }}
    </body>
</html>

参考资料使用Flask/Jinja2将HTML传递到模板


1
这个例子没有评估Jinja2表达式,这正是OP所要求的。 - Andreas Maier

0

如果您正在使用jinja 3.0版本,则contextfilter已被弃用并在Jinja 3.1中删除。请改用pass_context()。请参阅此处以获取更多相关细节。

from jinja2 import pass_context, Template
from markupsafe import Markup


@pass_context
def foo(context, value):
    return Markup(Template(value).render(context)).render()

然后在你的模板中

 {{ myvar|foo }}

Markup(...) 上的 render() 方法对我无效,我认为它没有这个方法。 - Andreas Maier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接