Mẫu Django cách tra cứu giá trị từ điển với một biến


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

Cách thông thường để tra cứu một giá trị từ điển trong một mẫu Django là {{ mydict.key1 }}, {{ mydict.key2 }}. Nếu khóa là biến vòng lặp thì sao? I E:

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

mydict.item.NAMEthất bại Làm thế nào để khắc phục điều này?

Câu trả lời:


361

Viết bộ lọc mẫu tùy chỉnh:

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

(Tôi sử dụng .getđể nếu khóa không có, nó sẽ không trả về. Nếu bạn làm điều dictionary[key]đó sẽ tăng lên KeyErrorsau đó.)

sử dụng:

{{ mydict|get_item:item.NAME }}

16
Tài liệu thẻ mẫu tùy chỉnh Django , cho những người tìm thấy điều này trong tương lai.
Jeff

281
Tại sao điều này không được xây dựng theo mặc định? :-(
Berislav Lopac


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

9
Bộ lọc có đi vào lượt xem không, một số bộ lọc bổ sung hay tập tin nào?
AlanSE

55

Lấy cả khóa và giá trị từ từ điển trong vòng lặp:

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

Tôi thấy điều này dễ đọc hơn và nó tránh được sự cần thiết phải mã hóa đặc biệt. Tôi thường cần khóa và giá trị bên trong vòng lặp nào.


28
Anh ta không yêu cầu liệt kê một dict (như bạn thể hiện) - anh ta yêu cầu lấy giá trị của dict đưa ra một khóa biến. Đề xuất của bạn không cung cấp giải pháp.
stag hành

Đó là một giải pháp (chỉ rất không hiệu quả) vì bạn có thể liệt kê các mục của dict và sau đó khớp với khóa từ danh sách.
DylanYoung

1
Lưu ý rằng điều này không hoạt động nếu từ điển bạn đang cố truy cập có chứa một từ điển khác bên trong.
J0ANMM

Nếu các giá trị của bạn là dicts, bạn có thể bao gồm một vòng lặp khác để xử lý các khóa và giá trị của chúng nhưng có khả năng sự phức tạp đang đưa bạn tới giá trị sử dụng bộ lọc tùy chỉnh như được mô tả trong câu trả lời của @ culebron.
Paul Whipp

36

Bạn không thể mặc định. Dấu chấm là dấu phân cách / kích hoạt để tra cứu thuộc tính / tra cứu khóa / lát.

Dấu chấm có một ý nghĩa đặc biệt trong kết xuất mẫu. Một dấu chấm trong một tên biến có nghĩa là một tra cứu. Cụ thể, khi hệ thống mẫu gặp một dấu chấm trong một tên biến, nó sẽ thử các tra cứu sau, theo thứ tự sau:

  • Tra cứu từ điển. Ví dụ: foo ["bar"]
  • Tra cứu thuộc tính. Ví dụ: foo.bar
  • Tra cứu danh sách chỉ mục. Ví dụ: foo [bar]

Nhưng bạn có thể tạo một bộ lọc cho phép bạn vượt qua trong một đối số:

https://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writer-custom-template-filters

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

{{ mydict|lookup:item.name }}

Tôi vẫn sẽ sử dụng return value.get(arg)vì điều đó sẽ không ném ngoại lệ KeyError nếu không có khóa.
slajma

3

Đối với tôi, việc tạo tệp python có tên template_filters.pytrong Ứng dụng của tôi với nội dung bên dưới đã thực hiện công việc

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

register = Library()


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

cách sử dụng giống như những gì culebrón đã nói:

{{ mydict|get_item:item.NAME }}

Tại sao register = Library()? Nó làm gì ?
MD. Khairul Basar

2
Nếu bạn muốn tất cả các mẫu của bạn biết về bộ lọc mới của bạn, thì bạn phải đăng ký nó dưới django.template.base.Librarylớp. bằng cách register = Library()chúng tôi khởi tạo lớp đó và sử dụng bộ filterchú thích hàm bên trong nó để đạt được nhu cầu của chúng tôi.
AmiNadimi

2

Tôi đã ở trong hoàn cảnh tương tự. Tuy nhiên tôi đã sử dụng một giải pháp khác.

Trong mô hình của tôi, tôi tạo một thuộc tính thực hiện tra cứu từ điển. Trong mẫu tôi sau đó sử dụng tài sản.

Trong mô hình của tôi: -

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

Trong mẫu của tôi: -

The state is: {{ item.state_ }}

1

Vì tôi không thể nhận xét, hãy để tôi thực hiện điều này dưới dạng câu trả lời:
để xây dựng câu trả lời của culebrón hoặc câu trả lời của Yuji 'Tomita' Tomita , từ điển được chuyển vào hàm dưới dạng chuỗi, vì vậy có lẽ nên sử dụng ast. lítal_eval để chuyển đổi chuỗi thành một từ điển đầu tiên, như trong ví dụ này .

Với chỉnh sửa này, mã sẽ trông như thế này:

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

{{ mydict|lookup:item.name }}

0

Môi trường: Django 2.2

  1. Mã ví dụ:


    from django.template.defaulttags import register

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

Tôi đặt mã này vào một tệp có tên template_filters.py trong thư mục dự án của tôi có tên portfoliomgr

  1. Bất kể bạn đặt mã bộ lọc ở đâu, hãy đảm bảo bạn có __init__.py trong thư mục đó

  2. Thêm tệp đó vào phần thư viện trong phần mẫu trong tệp projectfolder / settings.py của bạn. Đối với tôi, đó là 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. Trong mã html của bạn tải thư viện

    
    {% load template_filters %}

-2

env: django 2.1.7

lượt xem:

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

bản mẫu:

{% 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
Mã mẫu {{ dict_obj.obj.obj_name }}trong trường hợp này tương đương với mã Python dict_obj["obj"]["obj_name"], tuy nhiên, câu hỏi là tương đương với dict_obj[obj][obj_name].
Flimm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.