Django迭代字典时触发“dictionary changed size during iteration”错误
解决字典迭代时"dictionary changed size during iteration"错误的方案
问题重现
迭代包含列表的字典时触发错误,模板代码如下:
{% for wc in response %} <tr> <td>{{ response.wc }}</td> </tr> {% endfor %}
运行时抛出"dictionary changed size during iteration"异常,且确认未主动修改该字典。
核心原因
你虽未手动修改字典,但模板渲染过程中,部分框架(比如Django)会做惰性求值或动态属性生成操作——比如访问response.wc时,框架可能自动添加缓存属性到字典中,导致迭代过程中字典大小发生变化,触发错误。
正确解决方法
无需额外传入键列表,直接迭代字典的键的静态副本即可规避问题,有两种可行方式:
方式1:模板内直接迭代键的列表
修改模板代码,将迭代对象改为list(response.keys()),生成静态键列表后再循环:
{% for wc in list(response.keys()) %} <tr> <td>{{ response[wc] }}</td> </tr> {% endfor %}
注:response[wc]是字典键访问的标准写法,和response.wc在Django模板中效果一致,更符合字典操作逻辑。
方式2:视图层提前生成键列表
在视图处理阶段,先将字典的键转为静态列表传入模板上下文:
# 视图层代码 context['response_keys'] = list(response.keys())
模板中直接迭代这个预先生成的列表:
{% for wc in response_keys %} <tr> <td>{{ response[wc] }}</td> </tr> {% endfor %}
补充说明
- Python3中
response.keys()返回的是动态视图对象,若框架的动态属性生成操作发生在循环过程中,仍可能触发错误;转为list()后生成静态列表,可彻底避免迭代时字典结构变化的问题。
内容的提问来源于stack exchange,提问作者Rasmus Norup
相关产品推荐
相关产品推荐

