【问题标题】:Weird runtime error when looping over DefaultDict in django template在 django 模板中循环 DefaultDict 时出现奇怪的运行时错误
【发布时间】:2015-03-15 03:42:27
【问题描述】:

使用 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(&lt;type 'int'&gt;, {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])

一切正常。

任何线索任何人?

【问题讨论】:

  • 我猜想在 for 循环中你直接或间接访问了count_by_media_type.get('media_type'),所以defaultdict 被修改了。
  • 啊。你是对的。我正在通过 {{count_by_media_type.media_type}} 访问该值。我没有意识到这一点。谢谢,我放心了:)
  • 顺便说一句,您可能会发现循环遍历项目而不是键更容易:{% for media_type, count in count_by_media_type.iteritems %}{{ count }}{% endfor %}。您仍然必须使用下面我的答案中的修复方法之一。
  • 是的@Alasdair,让它成为一个字典肯定会做到这一点。但是,我继续使用 Counter Collection。也非常感谢您的回答。 Django Docs 真的很棒。

标签: python django


【解决方案1】:

由于模板变量查找的工作方式,使用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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-04-13
  • 2014-01-21
  • 2012-12-10
  • 2023-03-13
  • 1970-01-01
  • 2011-02-07
  • 2011-06-13
  • 1970-01-01
相关资源
最近更新 更多