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 %}
Другие вопросы по тегам