Jinja2递归循环解包报错:too many values to unpack
问题:Jinja2递归遍历文件树字典时触发解包错误
示例数据
{"smartphone":{"upload_1693308862":{"image1.png":{"url":"<url comes here>"},"image2.png":{"url":"<url comes here>"},"image3.png":{"url":"<url comes here>"},"image4.png":{"url":"<url comes here>"}}}}
所用Jinja2代码
{%- for level, subdict in file_structure.items() recursive %} <li> {%- if level.url -%} <a href="{{ level.url }}">{{ level }}</a> {% elif subdict is iterable and subdict is not string %} {{ level }} <ul class="submenu">{{ loop(subdict) }}</ul> {% else %} {{ level }} {% endif %} </li> {%- endfor %} </ul>
报错信息
2023-08-29T14:25:56.480784300Z {%- for level, subdict in file_structure.items() recursive %} 2023-08-29T14:25:56.480785800Z ValueError: too many values to unpack (expected 2)
疑问:dict.items()应返回键值对(两个值),为何会出现该解包错误?
解答
错误根源在递归调用的逻辑上:
- 当你执行
loop(subdict)时,传入的是子字典本身,而非它的items()。比如处理到image1.png对应的{"url": "..."}时,loop(subdict)会遍历这个字典的items(),得到("url", "<url comes here>"),但下一轮循环里的level, subdict会尝试把"url"这个字符串解包成两个值,直接触发解包错误。 - 另外你写的
level.url逻辑完全错误——level是字典的键(比如smartphone、image1.png),本质是字符串,根本不存在url属性,应该判断的是subdict里是否包含url键。
修正后的代码:
<ul> {%- for name, node in file_structure.items() recursive %} <li> {%- if node is mapping and node.get('url') %} <a href="{{ node.url }}">{{ name }}</a> {% elif node is mapping %} {{ name }} <ul class="submenu">{{ loop(node.items()) }}</ul> {% else %} {{ name }} {% endif %} </li> {%- endfor %} </ul>
关键修正点:
- 递归调用时传入
node.items(),确保每一轮循环都能拿到合法的键值对,避免解包错误 - 把判断逻辑改成检查
node(即键对应的值)是否是映射类型且包含url键,修正原有的属性访问错误 - 补上了开头的
<ul>标签,修复原代码HTML结构不闭合的问题
内容的提问来源于stack exchange,提问作者Standard
相关产品推荐
相关产品推荐

