【问题标题】:How to access a dictionary element in a Django template?如何访问 Django 模板中的字典元素?
【发布时间】:2017-03-09 00:15:24
【问题描述】:

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

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

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

此消息引发异常:

"Could not parse the remainder"

【问题讨论】:

    标签: python django django-templates


    【解决方案1】:
    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 控制迭代的顺序
    • 这应该是公认的答案。简单明了!
    【解决方案2】:

    你可以使用点符号:

    点查找可以概括为 this:当模板系统 在变量名中遇到一个点, 它尝试以下查找,在 这个顺序:

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

    系统使用第一种查找类型 这样可行。这是短路逻辑。

    【讨论】:

    • 在他的例子中,选择是一个变量。执行 .choice 将查找键“选择”的值,而不是键选择的值。
    • +1 获取信息,尽管这个问题有点像“猜猜我在想什么”的问题。谢谢威廉。
    • 这甚至适用于嵌套字典。 Python代码:my_dict[1][2]模板代码:my_dict.1.2
    • @J.C.Leitão 因为正确的版本是d.key.1 - 注意第二个.
    • 检查文档... from "1.6 docs.djangoproject.com/en/1.6/topics/templates/#variables" :请注意,像 {{ foo.bar }} 这样的模板表达式中的“bar”将被解释为文字字符串,并且如果模板上下文中存在变量“bar”的值,则不使用该值。
    【解决方案3】:

    为了回应/扩展 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 调用(如其他答案之一所示)是一个更简单的解决方案。
    【解决方案4】:

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

    标签定义:

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

    它的用法如下:

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

    【讨论】:

    • 考虑 h.get(key,'default_value') 因为 KeyError
    【解决方案5】:

    使用字典项:

    {% 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>
      

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

      【讨论】:

        【解决方案7】:

        django_template_filter 过滤器名称 get_value_from_dict

        {{ your_dict|get_value_from_dict:your_key }}
        

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

            找不到比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' }}
            

            【讨论】:

              【解决方案10】:

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

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

              ...做:

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

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

              【讨论】:

                猜你喜欢
                • 2014-09-10
                • 2014-10-05
                • 1970-01-01
                • 1970-01-01
                • 2021-05-20
                • 2011-07-11
                • 2021-10-17
                相关资源
                最近更新 更多