web-dev-qa-db-fra.com

Django template comment rechercher une valeur de dictionnaire avec une variable

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

Le moyen habituel de rechercher une valeur de dictionnaire dans un modèle Django est {{ mydict.key1 }}, {{ mydict.key2 }}. Et si la clé est une variable de boucle? c'est à dire:

{% 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 échoue. Comment régler ceci?

198
Stan

Écrivez un filtre de modèle personnalisé:

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

(J'utilise .get de sorte que si la clé est absente, elle n'en renvoie aucun. Si vous faites dictionary[key], une KeyError est alors déclenchée.)

usage:

{{ mydict|get_item:item.NAME }}
316
culebrón

Extrayez la clé et la valeur du dictionnaire dans la boucle:

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

Je trouve cela plus facile à lire et cela évite de recourir à un codage spécial. De toute façon, j'ai généralement besoin de la clé et de la valeur à l'intérieur de la boucle.

47
Paul Whipp

Vous ne pouvez pas par défaut. Le point est le séparateur/déclencheur de la recherche d'attribut/recherche de clé/tranche.

Les points ont une signification particulière dans le rendu des modèles. Un point dans un nom de variable signifie une recherche. Plus précisément, lorsque le système de modèles rencontre un point dans un nom de variable, il tente les recherches suivantes, dans cet ordre:

  • Recherche de dictionnaire. Exemple: foo ["bar"]
  • Recherche d'attribut. Exemple: foo.bar
  • Recherche par liste d'index. Exemple: foo [bar]

Mais vous pouvez créer un filtre qui vous permet de passer un argument:

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 }}
31

J'ai eu une situation similaire. Cependant, j'ai utilisé une solution différente.

Dans mon modèle, je crée une propriété qui effectue la recherche dans le dictionnaire. Dans le modèle, j'utilise ensuite la propriété.

Dans mon modèle: -

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

Dans mon modèle: -

The state is: {{ item.state_ }}
2
sexybear2

Pour moi, créer un fichier python nommé template_filters.py dans mon application avec le contenu ci-dessous fait le travail

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

register = Library()


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

l'usage est semblable à ce que dit culebrón:

{{ mydict|get_item:item.NAME }}
2
AmiNadimi

env: Django 2.1.7

vue:

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

modèle:

{% 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>
0
Yi Yang Apollo