ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

它会引发此消息的异常:

"Could not parse the remainder"

d
daaawx
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 的键和值。它应该仍然有效。
所以在模板引擎中不能使用()。顺便说一句,谢谢我。
这个问题的简洁的解决方案。澄清一下,items 是对字典的 Python 方法调用,而不是 Django 关键字。作为Alex Martelli points out,它与iteritems基本相同。正如 Wilhelm 回答的那样,字典查找在点查找中排名第三。如果您的字典中有一个名为 'items' 的项目,您将获得该值而不是元组列表。测试:将 {'items':'oops'} 添加到您的字典中,您将获得来自单词 'oops' 的字母的项目符号列表
使用 collections.OrderedDict 控制迭代的顺序
这应该是公认的答案。简单明了!
W
Wilhelm

您可以使用点符号:

点查找可以总结如下:当模板系统在变量名中遇到点时,它会尝试以下查找,按以下顺序: 字典查找(例如,foo["bar"]) 属性查找(例如,foo.bar ) 方法调用(例如 foo.bar()) 列表索引查找(例如 foo[2]) 系统使用第一个有效的查找类型。这是短路逻辑。


在他的情况下,选择是一个变量。执行 .choice 将查找键“选择”的值,而不是键选择的值。
为信息+1,即使这个问题有点像“猜猜我在想什么”的问题。谢谢威廉。
这甚至适用于嵌套字典。 Python 代码:my_dict[1][2] 模板代码:my_dict.1.2
@JCLeitão 因为正确的版本是 d.key.1 - 注意第二个 .
不过,请检查有关此的文档...来自“1.6 docs.djangoproject.com/en/1.6/topics/templates/#variables”:请注意,模板表达式中的“bar”(例如 {{ foo.bar }} 将被解释为文字字符串,而不是使用变量的值“ bar”,如果存在于模板上下文中。
V
Vishal Singh

为了回应/扩展 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。
您可以在此处找到该问题的答案:docs.djangoproject.com/en/dev/faq/models/… 实际上,它非常简单,可以显示在您的模板中,或使用日志记录工具进行记录,但您必须记住打开 DEBUG 才能使其正常工作。
这个解决方案非常适合我在使用 django 模板 + 谷歌应用引擎模型时遇到的问题。我希望我能两次投票给你。
虽然它确实有效,但它不是很有效。它在循环中执行 sql 查询(您应该避免这样做)。创建自己的标签来进行字典查找很容易:@register.filter def lookup(d, key): if d and isinstance(d, dict): return d.get(key)
创建一个类的开销太大了;一个结构更好的字典,结合 .items 调用(如其他答案之一所示)是一个更简单的解决方案。
S
Sardathrion - against SE abuse

您需要找到(或定义)一个“get”模板标签,例如 here

标签定义:

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

它的用法如下:

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

由于 KeyError 考虑 h.get(key,'default_value')
N
Nick Korolkov

django_template_filter 过滤器名称 get_value_from_dict

{{ your_dict|get_value_from_dict:your_key }}

A
Adam Starrh

类似于@russian_spy 的答案:

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

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


J
Jeff Ober

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


N
Nick Legend

找不到比 this solution 更简单更好的了。另见the doc

@register.filter
def dictitem(dictionary, key):
    return dictionary.get(key)

但是有一个问题(也讨论过here),返回的项目是一个对象,我需要引用这个对象的一个字段。不支持像 {{ (schema_dict|dictitem:schema_code).name }} 这样的表达式,所以我找到的唯一解决方案是:

{% with schema=schema_dict|dictitem:schema_code %}
    <p>Selected schema: {{ schema.name }}</p>
{% endwith %}

更新:

@register.filter
def member(obj, name):
    return getattr(obj, name, None)

所以不需要 with 标记:

{{ schema_dict|dictitem:schema_code|member:'name' }}

A
Aaron

您可以使用 namedtuple 而不是 dict。这是使用数据类的简写。代替

person = {'name':  'John', 'age':  14}

...做:

from collections import namedtuple
Person = namedtuple('person', ['name', 'age'])
p = Person(name='John', age=14)
p.name # 'John'

这与编写一个只保存数据的类相同。一般来说,我会避免在 django 模板中使用字典,因为它们很尴尬。