Как получить доступ к элементу словаря в шаблоне Django?

135

У меня есть этот код в шаблоне, который я хотел бы распечатать количество голосов, которое получил каждый выбор. голоса - это просто словарь, а выбор - это модельный объект.

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

он вызывает исключение из этого сообщения "Не удалось разобрать остаток"

Теги:

7 ответов

45
Лучший ответ

Чтобы повторить/распространить на комментарий Джеффа, я думаю, что вам следует стремиться, это просто свойство в вашем классе 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 состоит в том, чтобы изолировать вас от кода в ваших шаблонах и наоборот.

Я бы попробовал вышеуказанный метод и посмотрел, какой SQL генерирует ORM, поскольку я не уверен, что он будет предварительно кэшировать свойства и просто создать подзапрос для этого свойства или если он будет итеративно /on -demand запускает запрос для подсчета количества голосов. Но если он генерирует жестокие запросы, вы всегда можете заполнить свойство в своем представлении данными, которые вы собрали сами.

  • 0
    спасибо @john ewart, ваше решение сработало для меня. Я новичок в django и python и не могу понять, как получить sql, сгенерированный ORM.
  • 0
    Вы можете найти ответ на этот вопрос здесь: docs.djangoproject.com/en/dev/faq/models/… Это довольно просто, на самом деле и может быть отображено в вашем шаблоне или зарегистрировано с помощью средства ведения журнала, но вы должны не забудьте включить DEBUG, чтобы это работало.
Показать ещё 4 комментария
199
choices = {'key1':'val1', 'key2':'val2'}

Здесь шаблон:

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

В принципе, .items - это ключевое слово Django, которое разбивает словарь на список пар (ключ, значение). Это позволяет итерации по словарю в шаблоне Django.

  • 19
    .items - вы только что решили мою проблему.
  • 2
    это не сработало для меня.
Показать ещё 6 комментариев
143

вы можете использовать точечную нотацию:

Точные поиски можно суммировать как это: когда шаблонная система встречает точку в имени переменной, он пробует следующие поиски, в этот порядок:

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

Система использует первый тип поиска это работает. Его логика короткого замыкания.

  • 43
    В его случае выбор является переменной. Выполнение .choice будет искать значение для ключа «выбор», а не значение для выбора ключа.
  • 0
    +1 за информацию, хотя вопрос был своего рода вопросом «угадай, что я думаю». Спасибо, Вильгельм.
Показать ещё 4 комментария
14

Вам нужно найти (или определить) тег шаблона 'get', например здесь.

Определение тега:

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

И его использовать как:

{% for o in objects %}
  <li>{{ dictionary|hash:o.id }}</li>
{% endfor %}
  • 1
    рассмотрите h.get(key,'default_value') из-за KeyError
3

В идеале вы должны создать метод на объекте выбора, который попадает в число голосов, или создать связь между моделями. Тег шаблона, который выполнил поиск словаря, тоже будет работать.

2

Аналогично ответу @russian_spy:

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

Это может быть полезно для разбивки более сложных словарей.

2

django_template_filter имя фильтра get_value_from_dict

{{ your_dict|get_value_from_dict:your_key }}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню