Context behavior for jinja2 blocks with included files

Question:

I have difficulties understanding the context behavior when including files in Jinja2 blocks. See this minimal example:

base.jinja2

{% set foo="bar" %}

{% block content %}
{% include 'include.jinja2' %}
{% endblock content %}

include.jinja2

{{ foo }}

Rendering base.jinja2 produces the error foo' is undefined.

When I move the declaration of foo into the content block, the code renders correctly. So does it, when I move the include statement outside the content block, when I remove the content block around the include statement, or when I replace the include statement with the file’s contents.

Why is that? How can I use the global foo variable in the include file inside the content block?

Asked By: carlfriedrich

||

Answers:

Look at the link, section Block Nesting and Scope:

Blocks can be nested for more complex layouts. However, per default
blocks may not access variables from outer scopes:
The reason for this is that if the block is replaced by a child
template, a variable would appear that was not defined in the block or
passed to the context.

According to the document and starting with Jinja 2.2 you can change this behavior using scoped.

{% set foo="bar" %}

{% block content scoped %}
{% include 'include.jinja2' %}
{% endblock content %}

I agree that this is somehow weird, compared to what we are used to. But this is an intended feature.

Generally speaking, include is only passed the context. Since 2.1 it is
passed a derived context that is the original context + all the local
variables used before the include statement. This also means that if
you just use a variable from an outer scope, Jinja2 will track it as
local now and pass it to the derived context.

Answered By: maanijou
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.