Modello di Django come cercare un valore di dizionario con una variabile


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

Il modo normale di cercare un valore di dizionario in un modello Django è {{ mydict.key1 }}, {{ mydict.key2 }} . Cosa succede se la chiave è una variabile loop? vale a 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.NAMEnon riesce. Come risolvere questo?

Risposte:


362

Scrivi un filtro modello personalizzato:

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

(Lo uso in .getmodo che se la chiave è assente, non restituisce nessuna. Se lo fai dictionary[key], rilancia un KeyErrorallora.)

utilizzo:

{{ mydict|get_item:item.NAME }}


282
Perché questo non è integrato per impostazione predefinita? :-(
Berislav Lopac,

11
Penso che @Jeff intendesse la documentazione di Django Custom Template Filter
Jorge Leitao,

5
in Jinja2 {{mydict [chiave]}}
Evgeny

9
Il filtro va in views.py, qualche ulteriore filtro.py o quale file?
AlanSE,

56

Recupera sia la chiave che il valore dal dizionario nel loop:

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

Lo trovo più facile da leggere ed evita la necessità di una codifica speciale. Di solito ho comunque bisogno della chiave e del valore all'interno del loop.


28
Non ha chiesto di elencare un dict (come si vede) - ha chiesto di ottenere il valore del dict con una chiave variabile. La tua proposta non fornisce soluzione.
Staggart

È una soluzione (solo molto inefficiente) poiché è possibile enumerare gli elementi del dict e quindi associarli alla chiave dall'elenco.
DylanYoung,

1
Nota che questo non funziona se il dizionario a cui stai tentando di accedere contiene un altro dizionario all'interno.
J0ANMM,

Se i tuoi valori sono dicts, puoi includerne un altro per elaborare le loro chiavi e valori, ma è probabile che la complessità ti stia portando a valere la pena di usare un filtro personalizzato come descritto nella risposta di @ culebron.
Paul Whipp,

37

Non puoi per impostazione predefinita. Il punto è il separatore / trigger per la ricerca degli attributi / la ricerca dei tasti / la sezione.

I punti hanno un significato speciale nel rendering dei modelli. Un punto con un nome variabile indica una ricerca. In particolare, quando il sistema modello incontra un punto con un nome di variabile, prova le seguenti ricerche, in questo ordine:

  • Ricerca nel dizionario. Esempio: foo ["bar"]
  • Ricerca degli attributi. Esempio: foo.bar
  • Ricerca indice-elenco. Esempio: foo [bar]

Ma puoi creare un filtro che ti consente di passare un argomento:

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

1
Vorrei ancora utilizzare return value.get(arg)perché ciò non genererebbe un'eccezione KeyError se la chiave non è presente.
slajma,

3

Per me la creazione di un file Python denominato template_filters.pynella mia app con il contenuto di seguito ha fatto il lavoro

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

register = Library()


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

l'uso è come quello che ha detto Culebrón:

{{ mydict|get_item:item.NAME }}

Perché register = Library()? Che cosa fa ?
MD. Khairul Basar,

2
Se vuoi che tutti i tuoi modelli siano a conoscenza del tuo nuovo filtro, devi registrarlo in django.template.base.Libraryclasse. da register = Library()istanziamo quella classe e l'uso filterfunzione di annotazione al suo interno per raggiungere il nostro bisogno.
AmiNadimi,

2

Ho avuto una situazione simile. Tuttavia ho usato una soluzione diversa.

Nel mio modello creo una proprietà che esegue la ricerca nel dizionario. Nel modello utilizzo quindi la proprietà.

Nel mio modello: -

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

Nel mio modello: -

The state is: {{ item.state_ }}

1

Dal momento che non posso commentare, permettetemi di farlo sotto forma di una risposta:
per basarsi sulla risposta di Culebrón o sulla risposta di Tomji "Tomita" di Yuji , il dizionario passato alla funzione ha la forma di una stringa, quindi forse usare ast. literal_eval per convertire prima la stringa in un dizionario, come in questo esempio .

Con questa modifica, il codice dovrebbe apparire così:

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

{{ mydict|lookup:item.name }}

0

Ambiente: Django 2.2

  1. Codice di esempio:


    from django.template.defaulttags import register

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

Ho inserito questo codice in un file denominato template_filters.py nella cartella del mio progetto denominata portfoliomgr

  1. Indipendentemente da dove inserisci il codice del filtro, assicurati di avere __init__.py in quella cartella

  2. Aggiungi quel file alla sezione librerie nella sezione template nel tuo file projectfolder / settings.py. Per me, è 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. Nel tuo codice html carica la libreria

    
    {% load template_filters %}

-2

env: django 2.1.7

Visualizza:

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

modello:

{% 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
Il codice modello {{ dict_obj.obj.obj_name }}è in questo caso equivalente al codice Python dict_obj["obj"]["obj_name"], tuttavia la domanda riguarda l'equivalente di dict_obj[obj][obj_name].
Flimm,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.