Jijna2递归似乎总是产生深度超出错误

时间:2019-05-11 04:35:14

标签: python recursion jinja2

我以前从未使用过Jinja递归,但似乎应该可以相对理解。我在使用模板引擎渲染这种格式的数据时遇到麻烦。以下python代码是我尝试在Jinja中重现的一个很好的示例:

layers = {
    'groups': {
        'lower': {
            'groups': {},
            'layers': [{
                'layer_name': 'left #1',
            },
            {
                'layer_name': 'right #1',
            }]
        },
        'upper': {
            'groups': {},
            'layers': [{
                'layer_name': 'left',
            },
            {
                'layer_name': 'right',
            }]
        }
    },
    'layers': [{
        'layer_name': 'Background',
    }]
}

def printDict(_dict):
    for layer in _dict['layers']:
        print(layer['layer_name'])

    for group in _dict['groups']:
        print(group)
        printDict(_dict['groups'][group])

    printDict(layers)

我尝试使模板代码尽可能类似于上述工作逻辑,如下所示:

<ul>
    {% for node in layers recursive %}
        {% set outer_loop = loop %}
        {% if node == "layers" %}
            {% for layer in layers[node] %}
                <li>{{layer['layer_name']}}</li>
            {% endfor %}
        {% elif node == "groups" %}
            {% for group in layers[node] %}
                <li><b>{{group}}</b></li>
                <ul class="submenu">
                    {{ outer_loop(layers[node][group]) }}
                </ul>
            {% endfor %}
        {% endif %}
    {% endfor %}
</ul>

但是,每次我都得到“超出递归深度”。调试非常令人沮丧,因为在循环期间没有任何简单的调试器或方法可以打印值。谁能发现逻辑缺陷?

1 个答案:

答案 0 :(得分:1)

好吧,我最终想出一种可行的方法。问题在于Jinja具有非常奇怪的变量作用域。与python不同,在循环内部不会重新分配变量,而是继续使用原始的全局变量,这会导致无限循环条件。我通过在每个递归调用(和原始调用,保持一致)上使用“ .items()”方法解决了此问题,该方法在本地范围内创建了一个新变量(我相信,也许它也只是覆盖了全局范围内的变量) ,但无论哪种方法都可以)

<ul>
    {% for key, v in layers,items() recursive %}
        {% set outer_loop = loop %}
        {% if key == "layers" %}
            {% for layer in v %}
                <li>{{layer['layer_name']}}</li>
            {% endfor %}
        {% elif key == "groups" %}
            {% for group in v %}
                <li><b>{{group}}</b></li>
                <ul class="submenu">
                    {{ outer_loop(v[group].items()) }}
                </ul>
            {% endfor %}
        {% endif %}
    {% endfor %}
</ul>