【问题标题】:For loop inside block assignment?块分配内的循环?
【发布时间】:2021-11-20 00:47:47
【问题描述】:

这是一个基本循环,在赋值块之外编译得很好:

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

但是当我将循环放在assignment block 中时,就像这样

{% 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')

这个问题的动机是我使用宏来避免代码重复。例如,我有许多具有不同字段的 div。其中一个 div 包含给用户的消息。在一种(但只有一种)情况下,我想在这个 div 中包含一个 &lt;ul&gt;,所以我想循环遍历列表中的元素,将它们中的每一个包装在 &lt;li&gt; 标签中,然后传递结果html 作为宏的参数。因此我的问题。

是否可以在赋值块内使用 for 循环?还是有更好的方法来实现同样的目标?

【问题讨论】:

  • 你为什么用它?
  • 文档没有显示在赋值块内带有for-loop 的示例 - 所以可能无法使用它。而且我不知道生成一些带有值的 HTML 并稍后复制完全相同的 HTML 会有什么用处 - 因为它不能作为模板工作,它将使用不同的 items
  • @furas 我使用宏来避免代码重复。例如,我有许多具有不同字段的 div。其中一个 div 包含给用户的消息。在一种情况下,我想在这个 div 中包含一个&lt;ul&gt;,所以我想循环遍历列表中的元素,将每个元素包装在&lt;li&gt; 标签中,然后再将其传递给宏。因此我的问题。
  • @msailor 您在评论中提供给 furas 的信息非常重要。将其放在问题中,以便其他人在回答您的问题时可以指出实现相同目标的替代方法。
  • 它直接使用jinja 对其进行了测试,但我没有收到您的错误消息。但是set 有一个很大的缺点:它无法获取不同的变量,并且只能与items 一起使用。您应该将for-loop 放入macro stuff(items),然后您可以使用stuff(main_items)stuff(other_items)

标签: python flask jinja2


【解决方案1】:

基于AssertionError: Tried to resolve a name to a reference that was unknown to the frame,此问题仅存在于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()

【讨论】:

  • 我将提交一个问题,因为它似乎是一个错误。但是感谢您的解决方法!
猜你喜欢
  • 2014-12-19
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 2017-05-03
  • 1970-01-01
  • 1970-01-01
  • 2013-05-06
相关资源
最近更新 更多