แม่แบบ 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 }}

16
เอกสารแท็กเทมเพลต Django ที่กำหนดเองสำหรับผู้ที่ค้นหาสิ่งนี้ในอนาคต
Jeff

281
ทำไมค่าเริ่มต้นนี้ไม่ได้ถูกสร้างไว้ภายใน :-(
Berislav Lopac


5
ใน Jinja2 {{mydict [key]}}
Evgeny

9
ตัวกรองมีอยู่ใน views.py, ตัวกรองพิเศษบางอย่างหรือไฟล์ใดบ้าง
AlanSE

56

ดึงทั้งกุญแจและค่าจากพจนานุกรมในลูป:

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

ฉันพบว่าการอ่านนี้ง่ายขึ้นและหลีกเลี่ยงความต้องการการเข้ารหัสพิเศษ ฉันต้องการคีย์และค่าในลูปอยู่แล้ว


28
เขาไม่ได้ขอให้ระบุ dict (ตามที่คุณแสดง) - เขาขอให้รับค่าของ dict ที่กำหนดให้กับคีย์ตัวแปร ข้อเสนอของคุณไม่มีวิธีแก้ไข
staggart

มันเป็นวิธีการแก้ปัญหา (ไม่มีประสิทธิภาพมาก) เนื่องจากคุณสามารถระบุรายการของ dict แล้วจับคู่กับคีย์จากรายการ
DylanYoung

1
โปรดทราบว่าวิธีนี้ใช้ไม่ได้หากพจนานุกรมที่คุณพยายามเข้าถึงมีพจนานุกรมอื่นอยู่ภายใน
J0ANMM

หากค่าของคุณเป็น dicts คุณสามารถรวมอีกค่าสำหรับลูปเพื่อประมวลผลคีย์และค่าของพวกเขา แต่มีแนวโน้มว่าความซับซ้อนจะนำคุณไปสู่ความคุ้มค่าโดยใช้ตัวกรองที่กำหนดเองตามที่อธิบายไว้ในคำตอบ @ culebron
พอลวิปป์

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ในแอพของฉันด้วยเนื้อหาด้านล่างทำงานได้ดี

# 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()? มันทำอะไร ?
นพ. Khairul Basar

2
หากคุณต้องการให้แม่แบบของคุณทุกคนรู้เกี่ยวกับตัวกรองใหม่ของคุณคุณต้องลงทะเบียนในdjango.template.base.Libraryชั้นเรียน โดยregister = Library()เราสร้างอินสแตนซ์ของคลาสนั้นขึ้นมาและใช้filterฟังก์ชันคำอธิบายประกอบด้านในเพื่อเข้าถึงความต้องการของเรา
AmiNadimi

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

เนื่องจากฉันไม่สามารถให้ความเห็นได้ขอให้ฉันทำสิ่งนี้ในรูปแบบของคำตอบ:
เพื่อสร้างคำตอบของculebrónหรือคำตอบของ Tomita Yuji 'Tomita' Tomitaพจนานุกรมที่ส่งผ่านเข้าไปในฟังก์ชันจะอยู่ในรูปของสตริงดังนั้นอาจใช้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)

ฉันใส่รหัสนี้ในไฟล์ชื่อ template_filters.py ในโฟลเดอร์โครงการของฉันชื่อ portfoliomgr

  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 }}ในกรณีนี้เทียบเท่ารหัสหลามแต่คำถามคือเกี่ยวกับเทียบเท่าdict_obj["obj"]["obj_name"] dict_obj[obj][obj_name]
Flimm
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.