Render Jinja2 macro without worrying what the rest of the template

While working on my first Flask project, I came across a jinja2.exceptions.UndefinedError exception when trying to display a macro from a Jinja2 template. It turned out that Jinja2 throws this exception when it tries to parse the rest of the template, which does contain a reference to the global request object.

Here is the test.html template that I use for the test case:

<!doctype html> {% macro test_macro() -%} Rendered from macro {%- endmacro %} {{ request.authorization }} 

Bulb code # 1: display template (success):

 @app.route("/test") def test_view(): return render_template('test.html') 

Bulb Code # 2: Macro Rendering (Crash):

 @app.route("/test") def test_view(): test_macro = get_template_attribute('test.html', 'test_macro') return test_macro() 

If you select {{ request.authorization }} from the template, the second test will succeed.

Flag 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 now have working code, it’s inconvenient for me not to know why the second approach fails. Why is Jinja2 even worried about the rest of the template when it only needs to display a macro?

+7
python flask jinja2
source share
1 answer

You are absolutely right, it was caused on the side of Jinja. The get_template_attribute() method from the flask looks like this:

 return getattr(current_app.jinja_env.get_template(template_name).module, attribute) 

Therefore, it tries to get the name of the template, and then calling the module property evaluates this template before the property list is created. In your case, the reference to the request variable remained unknown to Jinja. See Jinja environment.py sources for more details.

0
source share

All Articles