Получить элемент списка динамически в шаблонах Django - PullRequest
18 голосов
/ 21 января 2012

У меня есть какой-то цикл на странице, и мне нужен элемент списка в зависимости от номера цикла.

Когда я звоню:

{{ mylist.1 }}
{{ mylist.2 }}
{{ mylist.3 }}

все работает нормально, но мне действительно нужно что-то вроде:

{% for x in somenumber|MyCustomRangeTag %}
    {{ mylist.x }}
{% endfor %}

MyCustomRangeTag дает мне Python range(), он работает, и у меня уже есть x в качестве числа. Так что x равно 1, 2, 3 и т. Д. В зависимости от номера цикла. Возможно ли это и как?

Ответы [ 4 ]

26 голосов
/ 21 января 2012

Это невозможно напрямую, потому что Джанго считает, что "x" является ключом для поиска в mylist - вместо значение для x.Итак, когда x = 5, Django пытается найти mylist["x"] вместо mylist[5].

. В качестве обходного пути используйте следующий фильтр:

@register.filter
def lookup(d, key):
    return d[key]

и используйте его как

{{ mylist|lookup:x }}
6 голосов
/ 21 января 2012

Я заметил, что @ e-sat упомянул об этом, но я думаю, что встроенный тег шаблона слайса заслуживает некоторой любви.

4 голосов
/ 22 ноября 2013

Тег среза в шаблонах Django может использовать код среза Python, но синтаксис безошибочно отличается. Например, если вы хотите получить элемент последовательности с переменной, в python вы напишите что-то похожее на следующее:

>>>mylist = ["0th Element", "1th Element"]
>>>zero, one = 0, 1
>>>mylist[zero]
"0th Element"
>>>mylist[one]
"1th Element"

Использование этого синтаксиса с тегом шаблона среза Django в каждом случае вернет нарезанный список сомнительной утилиты для получения элемента с известным индексом:

{% with "0" as zero %}
{% with "1" as one %}
{% with "2" as two %}

{{mylist|slice:zero}} {{mylist|slice:one}} {{mylist|slice:two}}

{% endwith %}
{% endwith %}
{% endwith %}

Отображает в HTML:

[] ["0th Element"] ["0th Element", "1th Element"]

Обратите внимание на различия: вы получаете результат mylist[:x] вместо mylist[x].

Django предоставляет достаточно инструментов, чтобы обойти это. Первый трюк заключается в использовании явных срезов, таких как 0:1 для ваших индексов, а затем |join:"" результирующий список в один элемент. Вот так:

{% with "0:1" as zero %}
{{mylist|slice:zero|join:""}}
{% endwith %}

Урожайность:

0th Element

Это особенно удобно, если вам нужен доступ к индексу родительского цикла при работе с итерируемым внутри дочернего цикла:

{% for parent in parent_loop %}
    {% cycle "0:1" "1:2" "2:3" as parent_loop_index silent %}
    {% for child in child_loop %}
        {{child|slice:parent_loop_index|join:""}}
    {% endfor %}
{% endfor %}

В комплекте только запасные части, хотя я не думаю, что Django реализовал достижения.

3 голосов
/ 21 января 2012

Вы уверены, что не можете просто сделать:

{% for item in mylist %}
    {{ item }}
{% endfor %}

С помощью фильтра срезов вы даже можете выполнить некоторые настройки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...