Bagaimana cara mengakses elemen kamus di templat Django?


181

Saya ingin mencetak jumlah suara yang didapat setiap pilihan. Saya memiliki kode ini di templat:

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

voteshanyalah sebuah kamus sementara choicesmerupakan objek model.

Itu memunculkan pengecualian dengan pesan ini:

"Could not parse the remainder"

Jawaban:


63

Untuk menggemakan / memperluas komentar Jeff, apa yang saya pikir harus Anda tuju hanyalah sebuah properti di kelas Pilihan Anda yang menghitung jumlah suara yang terkait dengan objek itu:

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

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

    votes = property(calculateVotes)

Dan kemudian di templat Anda, Anda dapat melakukan:

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

Tag templat, IMHO sedikit berlebihan untuk solusi ini, tetapi juga bukan solusi yang buruk. Tujuan dari template di Django adalah untuk melindungi Anda dari kode di template Anda dan sebaliknya.

Saya akan mencoba metode di atas dan melihat apa yang dihasilkan ORM SQL karena saya tidak yakin di atas kepala saya apakah itu akan melakukan pre-cache properti dan hanya membuat subselect untuk properti atau jika itu akan berulang / on- permintaan menjalankan kueri untuk menghitung jumlah suara. Tetapi jika itu menghasilkan pertanyaan mengerikan, Anda selalu dapat mengisi properti di tampilan Anda dengan data yang telah Anda kumpulkan sendiri.


terima kasih @john ewart, solusi Anda berhasil untuk saya. Saya pemula untuk Django dan Python dan tidak tahu bagaimana cara mendapatkan sql yang dihasilkan ORM.
Mohamed

Anda dapat menemukan jawabannya di sini: docs.djangoproject.com/en/dev/faq/models/... Cukup sederhana, sebenarnya, dan dapat ditampilkan di templat Anda, atau dicatat dengan fasilitas logging, tetapi Anda harus ingat untuk mengaktifkan DEBUG agar ini berfungsi.
John Ewart

solusi ini sangat cocok untuk masalah yang saya alami dengan django templating + google app engine model. Saya berharap saya bisa memilih Anda dua kali.
Conrad.Dean

5
Meskipun berhasil, itu tidak terlalu efisien. Itu melakukan query sql dalam satu lingkaran (sesuatu yang harus Anda hindari). Membuat tag Anda sendiri untuk melakukan pencarian dict mudah: @ register.filter def lookup (d, key): jika d dan isinstance (d, dict): return d.get (key)
dalore

Membuat kelas adalah terlalu banyak overhead; kamus terstruktur yang lebih baik, dikombinasikan dengan .itemspanggilan (seperti yang diilustrasikan dalam salah satu jawaban lain) adalah solusi yang jauh lebih sederhana.
Zags

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

Inilah templatnya:

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

Pada dasarnya, .itemsadalah kata kunci Django yang membagi kamus menjadi daftar (key, value)pasangan, seperti metode Python .items(). Ini memungkinkan iterasi di atas kamus dalam template Django.


@anacarolinats (dan lainnya) hanya memastikan Anda beralih pada kedua kunci, nilai untuk pilihan. item. Itu masih harus bekerja.
OldTinfoil

Akhirnya! Terima kasih!! : D
djGrill

jadi di mesin template tidak dapat menggunakan (). BTW Terima kasih banyak untuk saya.
BlaShadow

6
Solusi ringkas yang bagus untuk pertanyaan itu. Untuk memperjelas, itemsadalah panggilan metode Python di kamus, bukan kata kunci Django. Seperti yang ditunjukkan Alex Martelli , pada dasarnya sama dengan iteritems. Sebagai Wilhelm menjawab, pencarian kamus adalah 3 diutamakan untuk pencarian titik. Jika Anda memiliki item dalam kamus Anda bernama 'items', Anda akan mendapatkan nilai itu kembali daripada daftar tupel. Untuk menguji: tambahkan {'items':'oops'}ke kamus Anda dan Anda akan mendapatkan daftar surat
berpoin

1
Gunakan koleksi.
Diatur Dict

186

Anda dapat menggunakan notasi titik:

Pencarian titik dapat diringkas seperti ini: ketika sistem template menemukan titik dalam nama variabel, ia mencoba pencarian berikut, dalam urutan ini:

  • Pencarian kamus (mis., Foo ["bar"])
  • Pencarian atribut (misalnya, foo.bar)
  • Metode panggilan (mis., Foo.bar ())
  • Daftar-indeks pencarian (misalnya, foo [2])

Sistem menggunakan tipe pencarian pertama yang berfungsi. Ini logika hubungan pendek.


44
Dalam kasusnya pilihan adalah variabel. Melakukan .choice akan mencari nilai untuk "pilihan" kunci, bukan nilai untuk pilihan kunci.
ibz

Memberi +1 untuk info, meskipun pertanyaannya adalah pertanyaan "tebak apa yang saya pikirkan". Terima kasih Wilhelm.
eficker

1
Ini bahkan berfungsi dengan kamus bersarang. Kode python: Kode my_dict[1][2]templat:my_dict.1.2
djsmith

2
@ JCLeitão Karena versi yang benar adalah d.key.1- perhatikan yang kedua.
Izkata

3
Periksa dokumen tentang ini ... dari "1.6 docs.djangoproject.com/en/1.6/topics/templates/#variables ": Perhatikan bahwa "bar" dalam ekspresi templat seperti {{foo.bar}} akan ditafsirkan sebagai string literal dan tidak menggunakan nilai variabel "bar", jika ada dalam konteks templat.
jamesc

25

Anda perlu menemukan (atau menetapkan) tag templat 'dapatkan', misalnya, di sini .

Definisi tag:

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

Dan itu digunakan seperti:

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

3
pertimbangkan h.get(key,'default_value')karena KeyError
semiomant

9

Gunakan Item Kamus:

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


6

Mirip dengan jawaban oleh @russian_spy:

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

Ini mungkin cocok untuk memecah kamus yang lebih kompleks.


3

Idealnya, Anda akan membuat metode pada objek pilihan yang menemukan dirinya dalam suara, atau membuat hubungan antara model. Tag templat yang melakukan pencarian kamus juga akan berfungsi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.