渲染Jinja2宏而不打扰模板的其余部分 [英] Render Jinja2 macro without bothering what's in the rest of the template
问题描述
这是模板测试。 html用于测试用例:
<!doctype html>
{%macro test_macro() - %}
从宏
{% - endmacro%}
{{request.authorization}}
$ c $
-python prettyprint-override> @ app.route(/ test)
def test_view():
return render_template('test.html')
Flask code#2:呈现宏(失败):
@ app.route(/ test)
def test_view():
test_macro = get_template_attribute('test.html', 'test_macro')
return test_macro()
如果将 {{request.authorization}}
out from the template,the 2nd test will execute successfully。
Flask code#3:using the <解决方法我在Flask邮件中找到了一个解决方法(成功):
@ app.route(/ test )
def test_view():
t = app.jinja_env.get_template('test.html')
mod = t.make_module({'request':request})
return mod.test_macro()
尽管我现在有一个工作代码,但是我不觉得不知道为什么第二种方法失败。为什么Jinja2甚至在需要渲染宏的时候对模板的其余部分感到困扰呢?
解决方案 你是绝对正确的,它已经在金加方面造成了。来自Flask的方法 get_template_attribute()
看起来像这样:
return getattr (current_app.jinja_env.get_template(template_name).module,
attribute)
检索一个模板名称,然后调用属性 module
来计算这个模板,然后生成属性列表。在你的情况下,对Jinja的变量 request
的引用仍然是未知的。有关详情,请查看 Jinja的 environment.py
。来源
Working on my first Flask project, I stumbled upon jinja2.exceptions.UndefinedError exception when trying to render a macro from Jinja2 template. It turned out that Jinja2 generates this exception when it is trying to parse the rest of the template that indeed contains reference to the global request object.
Here is the template test.html I use for test case:
<!doctype html>
{% macro test_macro() -%}
Rendered from macro
{%- endmacro %}
{{ request.authorization }}
Flask code #1: rendering the template (success):
@app.route("/test")
def test_view():
return render_template('test.html')
Flask code #2: rendering the macro (fail):
@app.route("/test")
def test_view():
test_macro = get_template_attribute('test.html', 'test_macro')
return test_macro()
If you take the {{ request.authorization }}
out from the template, the 2nd test will execute successfully.
Flask code #3: using the workaround I found in the Flask mailing list archive (success):
@app.route("/test")
def test_view():
t = app.jinja_env.get_template('test.html')
mod = t.make_module({'request': request})
return mod.test_macro()
Although I have a working code now, I find it uncomfortable to not know why the 2nd approach fails. Why Jinja2 even bothers about the rest of the template when it is required to render only the macro?
You are absolutely right, it has been caused on the Jinja side. Method get_template_attribute()
from the Flask looks like this:
return getattr(current_app.jinja_env.get_template(template_name).module,
attribute)
So it tries to retrieve a template name, and afterward, call to the property module
evaluates this template before the list of the properties will be generated. In your case, the reference to the variable request
remained unknown for the Jinja. For more details check Jinja's environment.py
sources.
这篇关于渲染Jinja2宏而不打扰模板的其余部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!