Django模板如何使用变量查找字典值


234
mydict = {"key1":"value1", "key2":"value2"}

查找在Django模板字典值的常规方法是{{ mydict.key1 }}{{ mydict.key2 }}。如果键是循环变量怎么办?即:

{% for item in list %} # where item has an attribute NAME
  {{ mydict.item.NAME }} # I want to look up mydict[item.NAME]
{% endfor %}

mydict.item.NAME失败。如何解决?

Answers:


361

编写自定义模板过滤器:

from django.template.defaulttags import register
...
@register.filter
def get_item(dictionary, key):
    return dictionary.get(key)

(我.get这样使用,如果不存在该键,则不返回任何键。如果执行dictionary[key]此操作,则将引发一个KeyErrorthen。)

用法:

{{ mydict|get_item:item.NAME }}

16
Django Custom Template Tag文档,供以后发现的用户使用。
杰夫

281
为什么默认情况下不内置此功能?:-(
Berislav Lopac 2012年


5
在Jinja2 {{mydict [key]}}中
Evgeny

9
过滤器是否进入views.py,一些额外的filters.py或什么文件中?
AlanSE

56

从循环中的字典中获取键和值:

{% for key, value in mydict.items %}
    {{ value }}
{% endfor %}

我发现这更容易阅读,并且不需要特殊的编码。无论如何,我通常都需要循环内的键和值。


28
他没有要求枚举dict(如您所示)-他要求在给定变量键的情况下获得dict的值。您的建议不提供解决方案。
staggart,2015年

这是一个解决方案(效率很低),因为您可以枚举dict的项,然后与列表中的键匹配。
DylanYoung,2016年

1
请注意,如果您要访问的词典中包含另一个词典,则此方法不起作用。
J0ANMM

如果您的值是dict,则可以包括另一个for循环来处理其键和值,但很可能复杂性使您值得使用@culebron的答案中所述的自定义过滤器。
Paul Whipp

37

默认情况下不能。点是属性查找/键查找/切片的分隔符/触发器。

点在模板渲染中具有特殊含义。变量名称中的点表示查找。具体来说,当模板系统遇到变量名称中的点时,它将按以下顺序尝试以下查找:

  • 字典查找。示例:foo [“ bar”]
  • 属性查询。示例:foo.bar
  • 列表索引查找。示例:foo [bar]

但是您可以创建一个过滤器,以便您传递参数:

https://docs.djangoproject.com/zh-CN/dev/howto/custom-template-tags/#writing-custom-template-filters

@register.filter(name='lookup')
def lookup(value, arg):
    return value[arg]

{{ mydict|lookup:item.name }}

1
我仍会使用,return value.get(arg)因为如果键不存在,那不会抛出KeyError异常。
slajma

3

对我来说template_filters.py,用下面的内容在我的应用程序中创建一个名为python的文件就可以了

# coding=utf-8
from django.template.base import Library

register = Library()


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

用法就像culebrón所说的:

{{ mydict|get_item:item.NAME }}

为什么register = Library()呢 它有什么作用 ?
MD。Khairul Basar

2
如果您希望所有模板都知道新过滤器,则必须在django.template.base.Library类下注册它。通过register = Library()实例化该类并在其中使用filter函数注释器来满足我们的需求。
AmiNadimi

2

我也有类似的情况。但是我使用了不同的解决方案。

在我的模型中,我创建一个执行字典查找的属性。然后在模板中使用该属性。

在我的模型中:-

@property
def state_(self):
    """ Return the text of the state rather than an integer """
    return self.STATE[self.state]

在我的模板中:-

The state is: {{ item.state_ }}

1

因为我不能评论,让我做这一个答案的形式:
建立在culebrón的答案虞姬“富田”富田的答案,传递给函数的字典是一个字符串的形式,因此,也许使用AST。 literal_eval,首先将字符串转换为字典,如本例所示

通过此编辑,代码应如下所示:

@register.filter(name='lookup')
def lookup(value, arg):
    dictionary = ast.literal_eval(value)
    return value.get(arg)

{{ mydict|lookup:item.name }}

0

环境:Django 2.2

  1. 示例代码:


    from django.template.defaulttags import register

    @register.filter(name='lookup')
    def lookup(value, arg):
        return value.get(arg)

我将此代码放在名为Portfoliomgr的项目文件夹中的一个名为template_filters.py的文件中

  1. 无论您将过滤器代码放在何处,都要确保该文件夹中有__init__.py

  2. 将该文件添加到projectfolder / settings.py文件中模板部分的库部分。对我来说,它是Portfoliomgr / settings.py



    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR, 'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
                'libraries':{
                    'template_filters': 'portfoliomgr.template_filters',
                }
            },
        },
    ]
  1. 在您的html代码中加载库

    
    {% load template_filters %}

-2

环保:django 2.1.7

视图:

dict_objs[query_obj.id] = {'obj': query_obj, 'tag': str_tag}
return render(request, 'obj.html', {'dict_objs': dict_objs})

模板:

{% for obj_id,dict_obj in dict_objs.items %}
<td>{{ dict_obj.obj.obj_name }}</td>
<td style="display:none">{{ obj_id }}</td>
<td>{{ forloop.counter }}</td>
<td>{{ dict_obj.obj.update_timestamp|date:"Y-m-d H:i:s"}}</td>

1
{{ dict_obj.obj.obj_name }}在这种情况下,模板代码等效于Python代码dict_obj["obj"]["obj_name"],但是问题是关于的等效问题dict_obj[obj][obj_name]
Flimm
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.