#python #flask #jinja2
Вопрос:
Вот элементарный цикл, который отлично компилируется за пределами блока назначения:
{% for item in items %}
<p>{{item}}</p>
{% endfor %}
Но когда я помещаю цикл внутри блока назначения, вот так
{% set stuff %}
{% for item in items %}
<p>{{item}}</p>
{% endfor %}
{% endset %}
Я получаю AssertionError: Tried to resolve a name to a reference that was unknown to the frame ('item')
.
Мотивация вопроса заключается в том, что я использую макросы, чтобы избежать дублирования кода. Например, у меня есть несколько разделов с разными полями. Один из дивов содержит сообщение для пользователя. В одном (но только в одном) случае я хотел бы включить a <ul>
в этот div, и поэтому я хотел бы просмотреть элементы в списке, обернув каждый из них <li>
тегами, прежде чем передавать полученный html в качестве аргумента макросу. Отсюда и мой вопрос.
Можно ли использовать цикл for внутри блока назначения? Или есть лучший способ достичь того же самого?
Комментарии:
1. почему вы им пользуетесь?
2. документация не показывает примеров с
for
циклом внутри блока назначения-так что, вероятно, его невозможно использовать. И я не знаю, как было бы полезно сгенерировать некоторый HTML — код со значениями, а затем дублировать точно такой же HTML-код, потому что он не будет работать как шаблон, который будет использовать разныеitems
3. @furas Я использую макросы, чтобы избежать дублирования кода. Например, у меня есть несколько дивов с разными полями. Один из дивов содержит сообщение для пользователя. В одном случае я хотел бы включить a
<ul>
в этот div, и поэтому я хотел бы просмотреть элементы в списке, обернув каждый из них<li>
тегами, прежде чем передавать его в макрос. Отсюда и мой вопрос.4. @msailor Та информация, которую вы предоставили фурасу в комментарии, действительно важна. Поставьте это в вопрос, чтобы другие, отвечая на ваш вопрос, могли указать альтернативные способы достижения той же цели.
5. Он проверил это напрямую,
jinja
и я не получаю ваше сообщение об ошибке. Ноset
у него есть один большой недостаток: он не может получать разные переменные и работает только сitems
ними . Вы должны вставитьfor
-цикл,macro stuff(items)
а затем вы можете использоватьstuff(main_items)
,stuff(other_items)
Ответ №1:
На основе ошибки утверждения: Пытался разрешить имя ссылки, которая была неизвестна фрейму, эта проблема возникает только в Jinja2
версиях 3.x
. Старые версии 2.x
работают правильно.
В данный момент ему необходимо задать переменную, прежде чем вы будете использовать ее в блоке. Может быть, позже они это исправят.
{% set item = None %}
{% set stuff %}
{% for item in items %}
<p>{{item}}</p>
{% endfor %}
{% endset %}
{{ stuff }}
Но set
у меня есть один большой недостаток: он не может получить аргументы и работает только с items
ними .
И это не сработает, если я установлю {% set items = other_items %}
Я бы предпочел ввести код macro
для использования stuff(main_items)
stuff(other_items)
, и т. Д.
{% macro stuff(items) %}
{% for item in items %}
<p>{{item}}</p>
{% endfor %}
{% endmacro %}
{{ stuff(main_items) }}
{{ stuff(other_items) }}
Минимальный рабочий код:
from flask import Flask, render_template_string
app = Flask(__name__)
@app.route('/')
def index():
return render_template_string('''
<h1>SET</h1>
{% set item = None %}
{% set stuff_set %}
{% for item in items %}
<p>{{item}}</p>
{% endfor %}
{% endset %}
{{ stuff_set }}
<h1>MACRO</h1>
{% macro stuff_macro(items) %}
{% for item in items %}
<p>{{item}}</p>
{% endfor %}
{% endmacro %}
{{ stuff_macro(main_items) }}
{{ stuff_macro(other_items) }}
''', items=['A', 'B', 'C'], main_items=[1,2,3], other_items=[4,5,6])
if __name__ == '__main__':
#app.debug = True
app.run()
Комментарии:
1. Я подам жалобу, так как это похоже на ошибку. Но спасибо за обходной путь!