在 Django 模板中循环 DefaultDict 时出现奇怪的运行时错误

Weird runtime error when looping over DefaultDict in django template

使用 Django 1.5.1

我这里有一个简单的代码 -

count_by_media_type = defaultdict(int)
for user_media in user_media_data:
    count_by_media_type[user_media['media_type']] += 1

这是视图的一部分,使用 for 迭代循环在模板中呈现 -

{% for media_type in count_by_media_type %}
    ..........
{% endfor %}

循环中render_to_response方法之前count_by_media_type的值是 defaultdict(<type 'int'>, {u'photo': 1, u'audio': 4, u'video': 3})

但不知何故,在渲染时,迭代中出现运行时错误

dictionary changed size during iteration

并且在模板上下文中看到的 count_by_media_type 的值变为

defaultdict(<type 'int'>, {u'photo': 1, u'audio': 4, u'video': 3, u'media_type': 0})

这很奇怪,因为新键 media_type 是如何进入变量的?

现在,当我切换上面的代码时,在视图中提到

count_by_media_type = Counter([user_media['media_type'] for user_media in user_media_data])

一切正常。

有任何线索吗?

使用 defaultdicts 会导致 Django 模板出现奇怪的行为,这是因为模板变量查找的工作方式。请参阅 Django docs 幕后 框。

Django 文档建议在传递给模板之前将 defaultdict 转换为常规 dict

count_by_media_type = defaultdict(int)
for user_media in user_media_data:
    count_by_media_type[user_media['media_type']] += 1

count_by_media_type = dict(count_by_media_type)

或者,as this answer suggests,您可以在完成插入值后禁用默认功能。

count_by_media_type.default_factory = None