Jinja2: локальная/глобальная переменная

{% set disabled = '' %}
{% for voter in record.voters %}
    {% if user == voter %}
        {% set disabled = 'disabled' %}
    {% endif %}
    {{ disabled }}  # outputs: 'disabled'
{% endfor %}
{{ disabled }}  # outputs: ''

У меня есть этот шаблон в Jinja2. Что мне нужно, так это "отключенная" переменная, которая будет видна снаружи цикла "for". Это возможно?

4 ответов


самый простой способ справиться с этим-переместить логику, которая устанавливает disabled переменная для вашей функции просмотра и отправьте ее в шаблон, готовый к использованию. Смешивание логики приложения с презентацией не является хорошей идеей, шаблоны должны получать данные как можно более переваренными.

тем не менее, есть уродливый хак, который делает возможным то, что вы хотите, показано в принятом ответе на этот вопрос.

решение включает в себя включение do расширение для Jinja2 и использование его для изменения глобального массива. Для включения расширения используйте:

app.jinja_env.add_extension('jinja2.ext.do')

вот решение, адаптированное к вашему примеру:

{% set disabled = [] %}
{% for voter in record.voters %}
    {% if user == voter %}
        {% do disabled.append(1) %}
    {% endif %}
{% endfor %}
{% if disabled %}
    disabled
{% endif %}

вы можете использовать массив / dict, как предлагает Мигель, но вам не нужно расширение do как таковое; вы можете установить фиктивный var. Я использую следующее:

{% set glob={} %}

вверху, а затем в моем коде:

{% set _ = glob.update({'disabled':True}) %}

переменные _ - это просто манекен, вы не используете его впоследствии.


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

{% for item in list scoped %}
{% endfor %}

см.:http://jinja.pocoo.org/docs/templates/#block-nesting-and-scope


Я понимаю, что отвечаю на старую тему. Однако недавно я начал использовать Jinja и столкнулся с аналогичной проблемой: мне нужно было подсчитать количество напечатанных строк во вложенных циклах. Мое решение заключалось в том, чтобы обернуть переменную счетчика в класс и передать экземпляр шаблону. Аналогично, вы можете использовать класс-оболочку, как так

class VoterStatus(object):
    def __init__(self, status='active'):
        self._status = status

    def set_disabled(self):
        self._status = 'disabled'

    def __str__(self):
        return self._status

измените свой шаблон соответствующим образом

{% for voter in record.voters %}
    {% if user == voter %}
        {% status.set_disabled() %}
    {% endif %}
    {{ status }}  # outputs: 'disabled'
{% endfor %}

передать экземпляр класса состояния в шаблон для рендеринг:

tmplt.render(status=VoterStatus(), ...)

...а Боб - твой дядя.