Djangoテンプレート変数を使用して辞書値を検索する方法


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

Djangoテンプレートで辞書値を検索する通常の方法は{{ mydict.key1 }}{{ mydict.key2 }}です。キーがループ変数の場合はどうなりますか?つまり:

{% 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失敗します。これを修正するには?

回答:


362

カスタムテンプレートフィルターを記述します。

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


281
なぜこれがデフォルトで組み込まれていないのですか?:-(
Berislav Lopac


5
Jinja2で{{mydict [key]}}
Evgeny

9
フィルターはviews.py、いくつかの追加のfilters.py、またはどのファイルにありますか?
AlanSE 2015年

56

ループの辞書からキーと値の両方をフェッチします。

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

これは読みやすく、特別なコーディングの必要がありません。とにかく、ループ内のキーと値が必要です。


28
彼は(あなたが示すように)dictを列挙するように要求しませんでした-彼は可変キーを与えられたdictの値を取得するように要求しました。あなたの提案は解決策を提供しません。
staggart 2015年

辞書の項目を列挙して、リストのキーと照合できるため、これは解決策です(非常に非効率的です)。
DylanYoung

1
アクセスしようとしている辞書に別の辞書が含まれている場合、これは機能しないことに注意してください。
J0ANMM 2017年

値がdictの場合、キーと値を処理するために別のforループを含めることができますが、@ culebronの回答で説明されているように、カスタムフィルターを使用する価値があるために複雑になっている可能性があります。
ポールウィップ2017年

37

デフォルトではできません。ドットは、属性ルックアップ/キールックアップ/スライスのセパレーター/トリガーです。

ドットは、テンプレートのレンダリングで特別な意味を持ちます。変数名のドットはルックアップを意味します。具体的には、テンプレートシステムが変数名にドットを検出すると、次の検索をこの順序で試行します。

  • 辞書検索。例: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 }}

1
return value.get(arg)キーが存在しない場合はKeyError例外をスローしないため、引き続き使用します。
slajma

3

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()?それは何をするためのものか ?
MD。カイルバザール

2
すべてのテンプレートに新しいフィルターを知らせたい場合は、django.template.base.Libraryクラスに登録する必要があります。でregister = Library()、我々はそのクラスとインスタンスの使用filter、内部に機能アノテーターを私たちの必要性に到達します。
AmiNadimi 2017

2

私も同じような状況でした。ただし、別のソリューションを使用しました。

私のモデルでは、辞書検索を行うプロパティを作成します。次に、テンプレートでプロパティを使用します。

私のモデルでは:-

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

私のテンプレートでは:-

The state is: {{ item.state_ }}

1

コメントできないので、答えの形でこれをやってみましょう。クレブロンの答えまたは富田裕二の富田の答え
基づいて、関数に渡される辞書は文字列の形式なので、おそらくastを使用しますこの例のように、まず文字列を辞書に変換するliteral_eval

この編集により、コードは次のようになります。

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

{{ mydict|lookup:item.name }}

0

環境:Django 2.2

  1. コード例:


    from django.template.defaulttags import register

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

このコードを、portfoliomgrというプロジェクトフォルダーのtemplate_filters.pyというファイルに配置しました

  1. フィルターコードをどこに置いても、そのフォルダーに__init__.pyがあることを確認してください

  2. そのファイルを、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',
                }
            },
        },
    ]
  1. あなたのhtmlコードでライブラリをロードしてください

    
    {% load template_filters %}

-2

env: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>

1
{{ dict_obj.obj.obj_name }}この場合、テンプレートコードはPythonコードdict_obj["obj"]["obj_name"]と同等ですが、問題はと同等ですdict_obj[obj][obj_name]
Flimm
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.