如何在Django模板中访问字典元素?


181

我想打印出每个选择获得的票数。我在模板中有以下代码:

{% for choice in choices %}
    {{choice.choice}} - {{votes[choice.id]}} <br />
{% endfor %}

votes只是一个字典,而choices只是一个模型对象。

该消息引发异常:

"Could not parse the remainder"

Answers:


63

为了回应/扩展Jeff的评论,我认为您应该针对的只是Choice类中的一个属性,该属性计算与该对象关联的投票数:

    class Choice(models.Model):
        text = models.CharField(max_length=200) 

        def calculateVotes(self):
            return Vote.objects.filter(choice = self).count()

        votes = property(calculateVotes)

然后在模板中,您可以执行以下操作:

    {% for choice in choices %}
            {{choice.choice}} - {{choice.votes}} <br />
    {% endfor %}

模板标签,恕我直言,此解决方案有些过分,但也不是一个糟糕的解决方案。Django中模板的目标是使您与模板中的代码隔离,反之亦然。

我会尝试上述方法,并查看ORM生成的SQL,因为我不确定它是否会预先缓存属性并仅为该属性创建子选择,还是会迭代/启用-需求运行查询以计算投票数。但是,如果它产生了残酷的查询,您总是可以使用自己收集的数据填充视图中的属性。


谢谢@john ewart,您的解决方案对我有用。我是django和python的新手,无法弄清楚如何获取ORM生成的sql。
Mohamed

您可以在此处找到有关该问题的答案: docs.djangoproject.com/en/dev/faq/models/… 实际上,它非常简单,可以显示在模板中,也可以使用日志记录工具进行记录,但是您必须请记住打开DEBUG使其正常工作。
John Ewart

此解决方案非常适合django模板+ Google应用程序引擎模型遇到的问题。希望我能投票两次。
Conrad.Dean 2011年

5
虽然确实有效,但效率不是很高。它正在循环执行sql查询(您应避免这样做)。创建自己的标签来执行字典查找很容易:@ register.filter def lookup(d,key):if d and isinstance(d,dict):return d.get(key)
dalore 2012年

创建一个类会产生过多的开销。更好的结构化词典,与.items调用结合在一起(如其他答案之一所示)是一种简单得多的解决方案。
Zags 2014年

285
choices = {'key1':'val1', 'key2':'val2'}

这是模板:

<ul>
{% for key, value in choices.items %} 
  <li>{{key}} - {{value}}</li>
{% endfor %}
</ul>

基本上,.items是Django关键字,它将字典分为(key, value)成对的列表,很像Python方法.items()。这样可以在Django模板中的字典上进行迭代。


@anacarolinats(及其他)只需要确保您遍历choices.items的键,值。它仍然应该工作。
OldTinfoil

最后!谢谢!!:D
djGrill

因此在模板引擎中不能使用()。顺便说一句,谢谢我的沃克斯。
BlaShadow13年

6
这个问题很好的简洁解决方案。澄清items一下,是对字典的Python方法调用,而不是Django关键字。正如Alex Martelli所指出的,它与基本上相同iteritems。正如Wilhelm回答的那样,字典查找在点查找方面排在第三位。如果您的字典中有一个名为的项目'items',那么您将获得该值,而不是元组列表。测试:将其添加{'items':'oops'}到字典中,您会从单词'oops'中获得字母的项目符号列表
cod3monk3y 2013年

1
使用collections.OrderedDict控制迭代的顺序
dnalow

185

您可以使用点符号:

点查找可以总结如下:当模板系统遇到变量名称中的点时,它将按以下顺序尝试以下查找:

  • 字典查询(例如foo [“ bar”])
  • 属性查询(例如foo.bar)
  • 方法调用(例如foo.bar())
  • 列表索引查找(例如,foo [2])

系统使用有效的第一种查找类型。这是短路逻辑。


44
在他的情况下,选择是一个变量。执行.choice将查找键“ choice”的值,而不是键选择的值。
ibz 2011年

信息+1,即使该问题有点像“猜我在想什么”问题。谢谢威廉。
eficker

1
这甚至适用于嵌套字典。Python代码:my_dict[1][2]模板代码:my_dict.1.2
djsmith 2012年

2
@JCLeitão因为正确的版本是d.key.1-请注意第二个版本.
-Izkata

3
不过请检查文档...从“ 1.6 docs.djangoproject.com/en/1.6/topics/templates/#variables ”中:请注意,模板表达式中的“ bar”将被解释为{{foo.bar}}如果在模板上下文中存在一个字符串,则不使用变量“ bar”的值作为文字字符串。
jamesc 2013年

25

您需要在此处找到(或定义)“ get”模板标签。

标签定义:

@register.filter
def hash(h, key):
    return h[key]

它的用法如下:

{% for o in objects %}
  <li>{{ dictionary|hash:o.id }}</li>
{% endfor %}

3
考虑h.get(key,'default_value')由于
KeyError

9

使用字典项目:

{% for key, value in my_dictionay.items %}
  <li>{{ key }} : {{ value }}</li>
{% endfor %}


6

类似于@russian_spy的回答:

<ul>
{% for choice in choices.items %} 
  <li>{{choice.0}} - {{choice.1}}</li>
{% endfor %}
</ul>

这可能适合分解更复杂的字典。


3

理想情况下,您将在以投票方式发现自己的选择对象上创建方法,或者在模型之间创建关系。执行字典查找的模板标记也将起作用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.