Plantilla de Django cómo buscar un valor de diccionario con una variable
mydict = {"key1":"value1", "key2":"value2"}
La forma habitual de buscar un valor de diccionario en una plantilla de Django es {{ mydict.key1 }}
. {{ mydict.key2 }}
¿Qué pasa si la clave es una variable de bucle? es decir:
{% 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
falla. ¿Cómo arreglar esto?
Escribe un filtro de plantilla personalizado :
from django.template.defaulttags import register
...
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
(Lo uso .get
para que si la clave está ausente, no devuelva ninguna. Si lo hace, dictionary[key]
generará un KeyError
entonces).
uso:
{{ mydict|get_item:item.NAME }}
Obtenga tanto la clave como el valor del diccionario en el bucle:
{% for key, value in mydict.items %}
{{ value }}
{% endfor %}
Esto me resulta más fácil de leer y evita la necesidad de codificación especial. De todos modos, normalmente necesito la clave y el valor dentro del bucle.
No puedes por defecto. El punto es el separador/activador para la búsqueda de atributos/búsqueda de claves/sección.
Los puntos tienen un significado especial en la representación de plantillas. Un punto en el nombre de una variable significa una búsqueda. Específicamente, cuando el sistema de plantillas encuentra un punto en el nombre de una variable, intenta las siguientes búsquedas, en este orden:
- Búsqueda de diccionario. Ejemplo: foo["barra"]
- Búsqueda de atributos. Ejemplo: foo.bar
- Búsqueda de índice de lista. Ejemplo: foo[barra]
Pero puedes crear un filtro que te permita pasar un argumento:
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 }}
Para mí, crear un archivo Python nombrado template_filters.py
en mi aplicación con el contenido a continuación funcionó
# coding=utf-8
from django.template.base import Library
register = Library()
@register.filter
def get_item(dictionary, key):
return dictionary.get(key)
el uso es como lo que dijo culebrón:
{{ mydict|get_item:item.NAME }}
Entorno: Django 2.2
- Código de ejemplo:
from django.template.defaulttags import register
@register.filter(name='lookup')
def lookup(value, arg):
return value.get(arg)
Puse este código en un archivo llamado template_filters.py en la carpeta de mi proyecto llamada portfoliomgr
No importa dónde coloque su código de filtro, asegúrese de tener __init__.py en esa carpeta
Agregue ese archivo a la sección de bibliotecas en la sección de plantillas en su archivo carpeta de proyecto/settings.py. Para mí, es 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',
}
},
},
]
En tu código html carga la biblioteca
{% load template_filters %}
Tuve una situación similar. Sin embargo, utilicé una solución diferente.
En mi modelo creo una propiedad que realiza la búsqueda en el diccionario. En la plantilla luego uso la propiedad.
En mi modelo: -
@property
def state_(self):
""" Return the text of the state rather than an integer """
return self.STATE[self.state]
En mi plantilla: -
The state is: {{ item.state_ }}