Django şablonu nasıl bir değişken ile bir sözlük değeri arama


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

Django şablonunda bir sözlük değeri aramak için düzenli yoldur {{ mydict.key1 }}, {{ mydict.key2 }}. Anahtar bir döngü değişkeni ise ne olur? yani:

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

mydict.item.NAMEbaşarısız olur. Bunu nasıl düzeltirim?

Yanıtlar:


362

Özel bir şablon filtresi yazın:

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

( .getAnahtar yoksa, hiçbiri döndürmez. Bunu yaparsanız, dictionary[key]o zaman bir yükseltecektir KeyError.)

kullanımı:

{{ mydict|get_item:item.NAME }}


281
Bu neden varsayılan olarak yerleşik değil? :-(
Berislav Lopac


5
Jinja2'de {{mydict [key]}}
Evgeny

9
Filtre views.py, bazı ekstra filters.py veya hangi dosyaya giriyor?
AlanSE

56

Döngüdeki sözlükten hem anahtarı hem de değeri getir:

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

Bunu okumayı daha kolay buluyorum ve özel kodlama ihtiyacını ortadan kaldırıyor. Genellikle anahtar ve döngü içindeki değeri yine de gerekir.


28
Bir dikteyi numaralandırmak istemedi (gösterdiğiniz gibi) - değişken bir anahtar verildiğinde diktün değerini almak istedi. Teklifiniz çözüm sunmuyor.
staggart

Bu bir çözümdür (sadece çok verimsiz) çünkü diktenin öğelerini numaralandırabilir ve daha sonra listeden anahtarla eşleştirebilirsiniz.
DylanYoung

1
Erişmeye çalıştığınız sözlük içinde başka bir sözlük içeriyorsa, bunun çalışmadığını unutmayın.
J0ANMM

Değerleriniz dikte ise, döngü için anahtarlarını ve değerlerini işlemek için bir tane daha ekleyebilirsiniz, ancak karmaşıklığın sizi @ culebron'ın cevabında açıklandığı gibi özel bir filtre kullanmaya değecektir.
Paul Whipp

37

Varsayılan olarak yapamazsınız. Nokta, öznitelik arama / anahtar arama / dilim için ayırıcı / tetikleyicidir.

Şablon oluşturmada noktaların özel bir anlamı vardır. Değişken adındaki bir nokta aramayı gösterir. Özellikle, şablon sistemi değişken adında bir nokta ile karşılaştığında, bu sırayla aşağıdaki aramaları dener:

  • Sözlük araması. Örnek: foo ["bar"]
  • Özellik araması. Örnek: foo.bar
  • Liste dizini araması. Örnek: foo [bar]

Ancak bir argümanı iletmenize izin veren bir filtre yapabilirsiniz:

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
Yine de kullanacaktım return value.get(arg)çünkü anahtar yoksa bir KeyError istisnası atmazdı.
slajma

3

template_filters.pyUygulamamda aşağıdaki içeriğe sahip bir python dosyası oluşturmak benim için iş yaptı

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

register = Library()


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

culebrón'un söylediği gibi:

{{ mydict|get_item:item.NAME }}

Neden register = Library()? Bu ne işe yarıyor ?
MD. Khairul Basar

2
Tüm şablonlarınızın yeni filtreniz hakkında bilgi sahibi olmasını istiyorsanız, onu django.template.base.Librarysınıf altında kaydetmeniz gerekir . tarafından register = Library()o sınıf ve kullanım örneğini filteriçindeki fonksiyon yorumcu ihtiyacımızı ulaşmak için.
AmiNadimi

2

Benzer bir durum yaşadım. Ancak farklı bir çözüm kullandım.

Modelimde sözlük aramasını yapan bir özellik oluşturuyorum. Şablonda sonra özelliği kullanın.

Modelimde: -

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

Şablonumda: -

The state is: {{ item.state_ }}

1

Yorum yapamadığım için, bunu bir cevap şeklinde yapmama izin verin: culebrón'un cevabı veya Yuji 'Tomita' Tomita'nın cevabı
üzerine inşa etmek için , işleve geçirilen sözlük bir dize biçimindedir, belki de ast kullanın . Bu örnekte olduğu gibi, dizeyi önce bir sözlüğe dönüştürmek için literal_eval .

Bu düzenleme ile kod şöyle görünmelidir:

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

{{ mydict|lookup:item.name }}

0

Çevre: Django 2.2

  1. Örnek kod:


    from django.template.defaulttags import register

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

Bu kodu portfoliomgr adlı proje klasörümde template_filters.py adlı bir dosyaya koydum

  1. Filtre kodunuzu nereye koyarsanız koyun, o klasörde __init__.py olduğundan emin olun

  2. Bu dosyayı proje klasörü / settings.py dosyanızın şablonlar bölümündeki kitaplıklar bölümüne ekleyin. Benim için portföymgr / 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 kodunuza kitaplığı yükleyin

    
    {% load template_filters %}

-2

env: django 2.1.7

görünüm:

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

şablonu:

{% 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
Şablon kodu {{ dict_obj.obj.obj_name }}bu durumda Python koduna eşdeğerdir dict_obj["obj"]["obj_name"], ancak soru eşdeğeridir dict_obj[obj][obj_name].
Flimm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.