Làm thế nào để truy cập một phần tử từ điển trong mẫu Django?


181

Tôi muốn in ra số phiếu mà mỗi lựa chọn có được. Tôi có mã này trong một mẫu:

{% for choice in choices %}
    {{choice.choice}} - {{votes[choice.id]}} <br />
{% endfor %}

voteschỉ là một từ điển trong khi choiceslà một đối tượng mô hình.

Nó đưa ra một ngoại lệ với thông báo này:

"Could not parse the remainder"

Câu trả lời:


63

Để lặp lại / mở rộng theo nhận xét của Jeff, điều tôi nghĩ bạn nên nhắm đến chỉ đơn giản là một tài sản trong lớp Lựa chọn của bạn để tính toán số phiếu bầu liên quan đến đối tượng đó:

class Choice(models.Model):
    text = models.CharField(max_length=200)

    def calculateVotes(self):
        return Vote.objects.filter(choice=self).count()

    votes = property(calculateVotes)

Và sau đó trong mẫu của bạn, bạn có thể làm:

{% for choice in choices %}
    {{choice.choice}} - {{choice.votes}} <br />
{% endfor %}

Thẻ mẫu, IMHO hơi quá mức cho giải pháp này, nhưng nó cũng không phải là một giải pháp khủng khiếp. Mục tiêu của các mẫu trong Django là bảo vệ bạn khỏi mã trong các mẫu của bạn và ngược lại.

Tôi sẽ thử phương pháp trên và xem ORM tạo ra SQL nào vì tôi không chắc chắn về phía trên đầu của mình nếu nó sẽ lưu trước các thuộc tính và chỉ tạo một phần phụ cho thuộc tính hoặc nếu nó sẽ lặp lại / bật- nhu cầu chạy truy vấn để tính số phiếu. Nhưng nếu nó tạo ra các truy vấn tàn bạo, bạn luôn có thể điền vào tài sản trong chế độ xem của bạn với dữ liệu bạn tự thu thập.


cảm ơn @john ewart, giải pháp của bạn đã làm việc cho tôi. Tôi là người mới chơi django và python và không thể tìm ra cách lấy sql mà ORM tạo ra.
Mohamed

Bạn có thể tìm thấy câu trả lời cho bit đó tại đây: docs.djangoproject.com/en/dev/faq/models/. Nó khá đơn giản, thực sự và có thể được hiển thị trong mẫu của bạn hoặc đăng nhập với một cơ sở ghi nhật ký, nhưng bạn phải nhớ bật DEBUG để làm việc này.
John Ewart

giải pháp này là hoàn hảo cho một vấn đề tôi gặp phải với các mô hình công cụ ứng dụng django templating + google. Tôi ước tôi có thể bầu bạn lên hai lần.
Conrad.Dean

5
Trong khi nó hoạt động, nó không hiệu quả lắm. Nó đang thực hiện các truy vấn sql trong một vòng lặp (điều bạn nên tránh). Tạo thẻ của riêng bạn để thực hiện tra cứu dict thật dễ dàng: @ register.filter def lookup (d, key): if d và isinstance (d, dict): return d.get (key)
dinois

Tạo một lớp là quá nhiều chi phí; một từ điển có cấu trúc tốt hơn, kết hợp với .itemscuộc gọi (như được minh họa trong một trong những câu trả lời khác) là một giải pháp đơn giản hơn nhiều.
Zags

285
choices = {'key1':'val1', 'key2':'val2'}

Đây là mẫu:

<ul>
{% for key, value in choices.items %} 
  <li>{{key}} - {{value}}</li>
{% endfor %}
</ul>

Về cơ bản, .itemslà một từ khóa Django chia từ điển thành một danh sách các (key, value)cặp, giống như phương thức Python .items(). Điều này cho phép lặp lại từ điển trong mẫu Django.


@anacarolinats (và những người khác) chỉ cần đảm bảo rằng bạn lặp lại cả khóa, giá trị cho sự lựa chọn. Nó vẫn hoạt động.
OldTinfoil

Cuối cùng! Cảm ơn bạn!! : D
djGrill

vì vậy trong công cụ mẫu không thể sử dụng (). BTW Cảm ơn wotks cho tôi.
BlaShadow

6
Giải pháp ngắn gọn súc tích cho câu hỏi. Để làm rõ, itemslà một phương thức Python gọi từ điển, không phải từ khóa Django. Như Alex Martelli chỉ ra về cơ bản nó giống như iteritems. Như Wilhelm đã trả lời, việc tra cứu từ điển đứng thứ 3 trong việc tìm kiếm dấu chấm. Nếu bạn có một mục trong từ điển của mình được đặt tên 'items', bạn sẽ lấy lại giá trị đó thay vì danh sách các bộ dữ liệu. Để kiểm tra: thêm {'items':'oops'}vào từ điển của bạn và bạn sẽ nhận được một danh sách các chữ cái được đánh dấu từ từ 'oops'
cod3monk3y

1
Sử dụng các bộ sưu
tập.OrderedDict

186

bạn có thể sử dụng ký hiệu dấu chấm:

Tra cứu điểm có thể được tóm tắt như thế này: khi hệ thống mẫu gặp một dấu chấm trong 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)
  • Gọi phương thức (ví dụ: foo.bar ())
  • Tra cứu chỉ mục danh sách (ví dụ: foo [2])

Hệ thống sử dụng loại tra cứu đầu tiên hoạt động. Đó là logic ngắn mạch.


44
Trong trường hợp của mình sự lựa chọn là một biến. Làm .choice sẽ tra cứu giá trị cho "sự lựa chọn" thay vì giá trị cho lựa chọn khóa.
ibz

+1 cho thông tin, mặc dù câu hỏi là loại câu hỏi "đoán xem tôi đang nghĩ gì". Cảm ơn anh.
eficker

1
Điều này thậm chí hoạt động với từ điển lồng nhau. Mã Python: Mã my_dict[1][2]mẫu:my_dict.1.2
djsmith

2
@ JCLeitão Vì phiên bản chính xác là d.key.1- lưu ý lần thứ hai.
Izkata

3
Kiểm tra các tài liệu về điều này mặc dù ... từ "1.6 docs.djangoproject.com/en/1.6/topics/temsheet/#variabled ": Lưu ý rằng thanh bar thanh trong một biểu thức mẫu như {{foo.bar}} sẽ được diễn giải dưới dạng một chuỗi ký tự và không sử dụng giá trị của biến số thanh bar, nếu một chuỗi tồn tại trong bối cảnh mẫu.
jamesc

25

Bạn cần tìm (hoặc xác định) thẻ mẫu 'get', ví dụ, tại đây .

Định nghĩa thẻ:

@register.filter
def hash(h, key):
    return h[key]

Và nó được sử dụng như:

{% for o in objects %}
  <li>{{ dictionary|hash:o.id }}</li>
{% endfor %}

3
xem xét h.get(key,'default_value')vì KeyError
semiomant

9

Sử dụng các mục từ điển:

{% for key, value in my_dictionay.items %}
  <li>{{ key }} : {{ value }}</li>
{% endfor %}


6

Tương tự như câu trả lời của @russian_spy:

<ul>
{% for choice in choices.items %} 
  <li>{{choice.0}} - {{choice.1}}</li>
{% endfor %}
</ul>

Điều này có thể phù hợp để phá vỡ các từ điển phức tạp hơn.


3

Lý tưởng nhất là bạn sẽ tạo một phương thức trên đối tượng lựa chọn tự tìm thấy trong phiếu bầu hoặc tạo mối quan hệ giữa các mô hình. Một thẻ mẫu thực hiện tra cứu từ điển cũng sẽ hoạt động.

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.