Контекстное поведение для блоков jinja2 с включенными файлами

#python #django #flask #jinja2

#python #jinja2

Вопрос:

У меня возникают трудности с пониманием поведения контекста при включении файлов в блоки Jinja2. Смотрите этот минимальный пример:

base.jinja2

 {% set foo="bar" %}

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

включить.jinja2

 {{ foo }}
  

Рендеринг base.jinja2 выдает ошибку foo' is undefined .

Когда я перемещаю объявление foo в content блок, код отображается правильно. То же самое происходит, когда я перемещаю include инструкцию за пределы content блока, когда я удаляю content блок вокруг include инструкции или когда я заменяю include инструкцию содержимым файла.

Почему это? Как я могу использовать глобальную переменную foo во включаемом файле внутри блока содержимого?

Ответ №1:

Посмотрите на ссылку, раздел Block Nesting and Scope :

Блоки могут быть вложенными для более сложных макетов. Однако блоки по умолчанию не могут обращаться к переменным из внешних областей: Причина этого в том, что если блок заменить дочерним шаблоном, появится переменная, которая не была определена в блоке или передана в контекст.

В соответствии с документом и начиная с Jinja 2.2 вы можете изменить это поведение с помощью scoped .

 {% set foo="bar" %}

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

  

Я согласен, что это как-то странно по сравнению с тем, к чему мы привыкли. Но это предполагаемая функция.

Вообще говоря, include передается только контекст. Начиная с версии 2.1, передается производный контекст, который является исходным контекстом все локальные переменные, использованные до инструкции include. Это также означает, что если вы просто используете переменную из внешней области видимости, Jinja2 теперь будет отслеживать ее как локальную и передавать в производный контекст.

Комментарии:

1. Спасибо, это действительно работает. Но почему это работает без, scoped когда я не использую включаемый файл и ссылку foo непосредственно в моем content блоке?

2. Вообще говоря, include передается только контекст. Начиная с Jinja 2.1, передается производный контекст, который является исходным контекстом все локальные переменные, использованные до инструкции include. Это также означает, что если вы просто используете переменную из внешней области видимости, Jinja2 теперь будет отслеживать ее как локальную и передавать в производный контекст.