Django - получить элемент из итерируемого в шаблоне Django
Выполняя итерацию по списку в одном из моих шаблонов Django, я пытаюсь вставить некоторую логику if, чтобы сказать, что значение 'type' последнего элемента равно значению текущего элемента в значении 'type' цикла, но кажется, этот синтаксис Python для этого не допускается в шаблоне Django. Я знаю, что могу использовать {{ forloop.counter }}, но я не могу использовать этот счетчик, чтобы получить элемент из моего списка по определенному индексу.
HTML
{% for repair in repairs %}
{% if repairs[{{ forloop.counter - 1}}].type == repair.type %}<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ repair.type }}</h2></div>{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}</label>
</div>
{% endfor %}
или также
{% for index, repair in enumerate(repairs) %}
{% if repairs[index - 1].type == repair.type%}<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ repair.type }}</h2></div>{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}</label>
</div>
{% endfor %}
3 ответа
Вы должны быть в состоянии использовать ifchanged
за это.
{% for repair in repairs %}
{% ifchanged repair.type %}<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ repair.type }}</h2></div>{% endifchanged %}
...
{% endfor %}
Есть несколько проблем с вашим кодом.
Как отметил Джастин, шаблоны Django не позволяют вам получить доступ к элементу списка, используя что-то вроде list[index]
, Вместо этого вы должны сделать list.index
В шаблоне движка Django нет способа определить тип переменной. Однако вы можете реализовать шаблонный фильтр и использовать его для определения типа переменной, как описано в этом ответе.
Кроме того, вместо {{ forloop.counter - 1}}
, ты должен сделать {{ forloop.counter0 - 1}}
, forloop.counter
дает 1-индексированную итерацию цикла, тогда как forloop.counter0
дает 0-индексированную итерацию цикла.
Итак, ваш окончательный код должен выглядеть примерно так:
from django import template
register = template.Library()
@register.filter
def get_type(value):
return type(value)
{% for repair in repairs %}
{% if repairs.{{ forloop.counter0 - 1}}|get_type == repair|get_type %}
<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;">
<h2>{{ repair|get_type }}</h2>
</div>
{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}
</label>
</div>
{% endfor %}
Изменить: После того, как вы выяснили, что "тип" на самом деле является атрибутом переменной, вот что ваш код должен быть:
{% for repair in repairs %}
{% if repairs.{{ forloop.counter0 - 1}}.type == repair.type %}
<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;">
<h2>{{ repair.type }}</h2>
</div>
{% endif %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">
{{ repair }}
</label>
</div>
{% endfor %}
Конечно, метод, предложенный Даниэлем, является лучшим способом сделать это.
Есть встроенный тег шаблона для вашего варианта использования regroup
{% regroup repairs by type as types %}
{% for type in types %}
<div class="col-sm-12" style="border-top: 1px solid grey; border-bottom: 1px solid grey;"><h2>{{ type.grouper}}</h2></div>
{% for repair in type.list %}
<div class="col-sm-6">
<label>
<input type="checkbox" name="{{ repair }}">{{ repair }}
</label>
</div>
{% endfor %}
{% endfor %}