Як отримати доступ до елемента словника в шаблоні Django?


181

Я хотів би роздрукувати кількість голосів, які отримав кожен вибір. Я маю цей код у шаблоні:

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

votesє лише словником, а choicesє об'єктом моделі.

Він створює виняток із цього повідомлення:

"Could not parse the remainder"

Відповіді:


63

Щоб повторити / продовжити коментар Джеффа, я думаю, що вам слід прагнути, це просто властивість у вашому класі Choice, яка обчислює кількість голосів, пов'язаних із цим об'єктом:

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

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

    votes = property(calculateVotes)

І тоді у своєму шаблоні ви можете:

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

Тег шаблонів - це IMHO трохи надмірне для цього рішення, але це теж не страшне рішення. Мета шаблонів у Django - ізолювати вас від коду у ваших шаблонах і навпаки.

Я б спробував вищевказаний метод і побачив, що створює ORQL, оскільки я не впевнений, що він буде попередньо кешувати властивості та просто створити підвідбір для властивості або якщо він буде ітеративно / ввімкнено- попит, запустіть запит, щоб обчислити підрахунок голосів. Але якщо це генерує зарозумілі запити, ви завжди можете заповнити ресурс у вашому представленні даними, які ви зібрали самостійно.


дякую @john ewart, ваше рішення працювало на мене. Я новачок у django та python і не можу зрозуміти, як отримати sql, що ORM генерується.
Мохамед

Ви можете знайти відповідь на цей біт тут: docs.djangoproject.com/en/dev/faq/models/… Це дуже просто, насправді і може відображатися у вашому шаблоні або входити в систему за допомогою журналу, але вам потрібно не забудьте ввімкнути DEBUG, щоб це працювало.
Джон Еварт

це рішення ідеально підходить для проблеми, з якою я стикався з шаблонами django + моделі двигуна додатків google. Я хотів би, щоб я міг проголосувати за вас двічі.
Conrad.Dean

5
Хоча це працює, це не дуже ефективно. Він робить запити sql в циклі (чого слід уникати). Створити власний тег для пошуку диктувань легко: @ register.filter def lookup (d, key): якщо d та isin substance (d, dict): return d.get (ключ)
dalore

Створення класу - це занадто великі витрати; краще структурований словник у поєднанні з .itemsвикликом (як показано в одній з інших відповідей) є набагато простішим рішенням.
Загс

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

Ось шаблон:

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

По суті, .itemsце ключове слово Django, яке розбиває словник до списку (key, value)пар, як і метод Python .items(). Це дозволяє ітерацію словника в шаблоні Django.


@anacarolinats (та інші) просто переконайтеся, що ви переймете обидва ключові значення, що стосуються choices.items. Це все одно має працювати.
OldTinfoil

Нарешті! Дякую!! : D
djGrill

тому в двигуні шаблонів не можна використовувати (). BTW Спасибі wotks для мене.
BlaShadow

6
Приємне стисле вирішення питання. Для уточнення items- це виклик методу Python у словнику, а не ключове слово Django. Як зазначає Алекс Мартеллі, це в основному те саме, що iteritems. Як відповів Вільгельм, пошук словника є третім за пріоритетом у пошуках крапок. Якщо у вашому словнику є елемент з назвою 'items', ви отримаєте це значення замість списку кортежів. Для тестування: додайте {'items':'oops'}до свого словника, і ви отримаєте маркований список букв від слова 'oops'
cod3monk3y

1
Використовуйте колекції.
OrdDict,

186

Ви можете використовувати позначення крапки:

Шукання точок може бути узагальнено таким чином: коли система шаблонів стикається з крапкою в імені змінної, вона намагається виконати наступні пошуки в такому порядку:

  • Пошук словника (наприклад, foo ["bar"])
  • Пошук атрибутів (наприклад, foo.bar)
  • Виклик методу (наприклад, foo.bar ())
  • Пошук списку-індексу (наприклад, foo [2])

Система використовує перший тип пошуку, який працює. Це логіка короткого замикання.


44
У його випадку вибір є змінною. Роблячи .choice буде шукати значення для ключа "вибір", а не значення для вибору ключа.
ibz

+1 для інформації, навіть якщо це запитання було на зразок "здогадайтесь, що я думаю". Дякую Вільгельму.
eficker

1
Це навіть працює з вкладеними словниками. Код Python: Код my_dict[1][2]шаблону:my_dict.1.2
djsmith

2
@ JCLeitão Оскільки правильна версія є d.key.1- зверніть увагу на другу.
Ізката

3
Перевірте документи на цьому, хоч ... з "1.6 docs.djangoproject.com/en/1.6/topics/templates/#variables ": Зауважте, що "bar" у виразі шаблону на зразок {{foo.bar}} буде інтерпретовано як буквальний рядок і не використовує значення змінної "bar", якщо така існує в контексті шаблону.
jamesc

25

Потрібно знайти (або визначити) тег шаблону "отримати", наприклад, тут .

Визначення тегу:

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

І використовується так:

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

3
вважайте, h.get(key,'default_value')тому що KeyError
семіомант



6

Схожа на відповідь @russian_spy:

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

Це може бути зручним для розбиття складніших словників.


3

В ідеалі ви б створили метод на об'єкті вибору, який опинився в голосах, або створили взаємозв'язок між моделями. Тег шаблону, який здійснював пошук словника, також працював.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.