ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

{% 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 失败。如何解决这个问题?


p
pyjavo

写一个 custom template filter

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

(我使用 .get 以便如果密钥不存在,它不会返回任何内容。如果你这样做 dictionary[key] 它会引发一个 KeyError 然后。)

用法:

{{ mydict|get_item:item.NAME }}

Django Custom Template Tag documentation,对于那些在未来发现这一点的人。
为什么这不是默认内置的? :-(
我认为@Jeff 的意思是Django Custom Template Filter documentation
在 Jinja2 {{ mydict[key] }}
过滤器是放在views.py、一些额外的filters.py还是什么文件中?
P
Paul Whipp

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

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

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


他没有要求枚举字典(如您所示) - 他要求在给定变量键的情况下获取字典的值。您的建议没有提供解决方案。
这是一个解决方案(只是非常低效),因为您可以枚举 dict 的项目,然后与列表中的键匹配。
请注意,如果您尝试访问的字典中包含另一个字典,则此方法不起作用。
如果您的值是 dicts,您可以包含另一个 for 循环来处理它们的键和值,但很可能复杂性使您倾向于使用 @culebron 的答案中描述的自定义过滤器。
@PaulWhipp 我有同样的问题,但键有多个值,当我尝试你的答案时,它只显示第一个值。
A
Alasdair

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

点在模板渲染中具有特殊的含义。变量名中的点表示查找。具体来说,当模板系统在变量名中遇到点时,它会按以下顺序尝试以下查找: 字典查找。示例: foo["bar"] 属性查找。示例: foo.bar 列表索引查找。示例:foo[bar]

但是你可以制作一个过滤器,让你传入一个参数:

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

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

{{ mydict|lookup:item.name }}

我仍然会使用 return value.get(arg),因为如果密钥不存在,它不会引发 KeyError 异常。
返回值.get(arg, None)
A
AmiNadimi

对我来说,在我的应用程序中创建一个名为 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() ?它有什么作用 ?
如果您希望您的所有模板都知道您的新过滤器,那么您必须在 django.template.base.Library 类下注册它。通过 register = Library() 我们实例化该类并在其中使用 filter 函数注释器来满足我们的需要。
s
sexybear2

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

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

在我的模型中: -

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

在我的模板中: -

The state is: {{ item.state_ }}

K
Krishna

环境:Django 2.2

示例代码:



    from django.template.defaulttags import register

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

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

无论您将过滤器代码放在哪里,请确保该文件夹中有 __init__.py 将该文件添加到 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',
                }
            },
        },
    ]

在您的 html 代码中加载库 {% load template_filters %}


N
NJHJ

由于我无法发表评论,让我以答案的形式这样做:
culebrón's answerYuji 'Tomita' Tomita's answer 为基础,传递给函数的字典是字符串形式,所以也许使用 { 3} 首先将字符串转换为字典,如 this example

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

# code for custom template tag
@register.filter(name='lookup')
def lookup(value, arg):
    value_dict = ast.literal_eval(value)
    return value_dict.get(arg)
<!--template tag (in the template)-->
{{ mydict|lookup:item.name }}

是否可以将返回的值({{ mydict|lookup:item.name }})分配给变量
@Jibin 我不确定你的问题是什么意思。也许我的代码令人困惑;从那时起,我已对其进行了更正并添加了评论。
@Jibin 来自 grails/gsp 和其他模板语言我有同样的问题 - 但在 django 中需要考虑不同:你可以在渲染模板之前这样做。当您在视图中为模板创建上下文时,您只需将瞬态属性和(我相信)甚至方法添加到您的模型对象并从模板中访问它们 - 非常适合您在该模板中需要的所有临时内容,并且非常易读模板代码。
Y
Yi Yang Apollo

环境: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>

在这种情况下,模板代码 {{ dict_obj.obj.obj_name }} 等同于 Python 代码 dict_obj["obj"]["obj_name"],但是,问题是关于 dict_obj[obj][obj_name] 的等价物。
在模板中如何使用答案?