【问题标题】:Looping problem with dictionary in Django templatesDjango模板中的字典循环问题
【发布时间】:2011-09-19 04:17:27
【问题描述】:

我不确定为什么这个模板没有向页面呈现任何内容。 我在这里有什么明显的遗漏吗?

查看:

@user_passes_test(is_staff)
def details_activity_log(request, project_id, template='projects/details_activity_log.html'):

    project = get_object_or_404(Project.objects.select_related(), pk=project_id)
    action_log = project.projectactionlog_set.all()

    log_group = defaultdict(list)

    for log in action_log:
        log_group[log.action_time.strftime('%y%m%d')].append(log)


    #import pdb; pdb.set_trace()

    return render_to_response(template, {
        'log_group'  : log_group,
        'project'    : project,
        'action_log' : action_log,
        'tab_5'      : 'active',
    }, context_instance=RequestContext(request))

log_group 包含一个 dict 模型对象,如下所示:

defaultdict(<type 'list'>, {'110614': [<ProjectActionLog: ProjectActionLog object>, ...]}) 

模板:

   {% for key, log in log_group %}
      {% for action in log %}
        {{ action }}
        {{ action.action_time }}                    
        {{ action.user.first_name }}
        {{ action.message }}
        {{ action.object_name }}
      {% endfor %}
    {% endfor %}

编辑 如果我查看了文档,我就会看到答案。 https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for

但这是一个棘手的情况,因为当循环无法解压缩迭代器项时,模板不会引发任何运行时错误。

【问题讨论】:

标签: python django django-templates


【解决方案1】:

还要非常小心使用 django 模板中的 defaultdicts,我在您的代码中看到您确实在使用 defaultdict

由于 django 尝试访问属性/属性/等的方式,它们显然不能在模板中按预期工作。唯一的解决方案是将它们转换为字典:

context['dictstructure'] = dict(mydefaultdict)

template documentation 已在 ticket #16335changeset 之后进行了修补,以包含有关此问题的特别通知。

从技术上讲,当模板系统遇到 点,它会按以下顺序尝试以下查找:

  • 字典查找
  • 属性查找
  • 方法调用
  • 列表索引查找

这可能会导致覆盖的对象出现一些意外行为 字典查找。例如,考虑以下代码 sn -p 尝试遍历 collections.defaultdict:

{% for k, v in defaultdict.iteritems %}
    Do something with k and v here... 
{% endfor %} 

因为首先发生字典查找,所以该行为会启动并提供默认值 值而不是使用预期的 .iteritems() 方法。在这种情况下, 考虑先转换成字典。

另请参阅问题Django template can't loop defaultdict

【讨论】:

    【解决方案2】:

    将你的 for 循环更新为:

    {% for log in log_group.itervalues %}
    

    或者,如果您确实需要key(您的示例模板没有显示您使用它):

    {% for key, log in log_group.iteritems %}
    

    【讨论】:

      【解决方案3】:

      改变

      {% for key, log in log_group %}
      

      {% for key, log in log_group.items %}
      

      【讨论】:

      • 更好:log_group.iteritems。但在这种情况下,他似乎没有使用key,所以itervalues 应该这样做。
      • 您能解释一下这是为什么吗?通过一些搜索,我发现 iteritems 是一个生成器,并且延迟加载占用较少 RAM 的项目?对吗?
      • 他是正确的,使用 iter* 方法通常更好。副作用是,如果您需要多次循环遍历字典,通常最好将其加载到内存中(除非它很大)。如果您的 dict 相当小,则两者之间的差异在个人基础上可以忽略不计。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-03
      • 2015-11-25
      • 2016-08-31
      • 1970-01-01
      • 2016-10-11
      • 1970-01-01
      相关资源
      最近更新 更多