Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
891 views
in Technique[技术] by (71.8m points)

python - For loop inside block assignment?

Here's an elementary loop, which compiles fine when outside of an assignment block:

{% for item in items %}
  <p>{{item}}</p>
{% endfor %}

But when I place the loop inside of an assignment block, like so

{% set stuff %}
  {% for item in items %}
    <p>{{item}}</p>
  {% endfor %}
{% endset %}

I get AssertionError: Tried to resolve a name to a reference that was unknown to the frame ('item').

The motivation for the question is that I am using macros to avoid code duplication. E.g., I have a number of divs with different fields. One of the divs contains a message to the user. In one (but only one) case, I would like to include a <ul> in this div, and so I would like to loop through the elements in a list, wrapping each of them in <li> tags, before passing the resulting html as an argument to the macro. Hence my question.

Is it possible to use a for loop inside of an assignment block? Or is there a better way of achieving the same thing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Based on AssertionError: Tried to resolve a name to a reference that was unknown to the frame this problem is only in Jinja2 versions 3.x. Older versions 2.x works correctly.

At this moment it needs to set variable before you use it in block. Maybe later they fix it.

{% set item = None %}

{% set stuff %}
  {% for item in items %}
    <p>{{item}}</p>
  {% endfor %}
{% endset %}

{{ stuff }}

But set has one big drawback for me: it can't get arguments and it works only with items.
And it can't works if I set {% set items = other_items %}

I would rather put code in macro to use stuff(main_items), stuff(other_items), etc.

{% macro stuff(items) %}
  {% for item in items %}
    <p>{{item}}</p>
  {% endfor %}
{% endmacro %}

{{ stuff(main_items) }}

{{ stuff(other_items) }}

Minimal working code:

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()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...