Django/Python: цикл по выбранным полям формы в шаблоне Django

У меня есть форма с n полями. Первые 4 поля должны отображаться в моем шаблоне иначе, чем остальная часть формы. Поэтому мне было интересно, могу ли я как-то зациклиться на первых 4 полях, завершить цикл и продолжить цикл по остальным полям позже в шаблоне.

        <table>
            {% for field in form %}
            {% if forloop.counter == 4 <<< Break here >>>%}
            <tr>
                <td> {{ field.label_tag }} </td>
                <td> {{ field }} </td>
            </tr>
            {% endfor %}
        </table>
        .... Different code ....
        <table>
            {% for field in form %} <<< Continue here >>>
            <tr>
                <td> {{ field.label_tag }} </td>
                <td> {{ field }} </td>
            </tr>
            {% endfor %}
        </table>

Я нашел этот код, но мне было интересно, могу ли я структурировать шаблон по-другому или я пропустил некоторые новые изменения в Django 1.3, которые теперь позволяют прерывать циклы.

Обычно я бы разделил форму на две отдельные формы, но я хотел бы повторно использовать определение формы и в других шаблонах, поэтому я хотел бы хранить всю информацию вместе в одной форме.

Спасибо за ваш совет!


person neurix    schedule 13.12.2011    source источник


Ответы (5)


Это такое же решение, как и другие проблемы «невозможно сделать это в шаблоне»: сделайте это в представлении. Я действительно считаю, что дополнительная сложность и дальнейшее разделение логики на несколько областей кода (теги, новые файлы и т. д.) только ухудшают удобство сопровождения. Я разделяю/внедряю DRY только тогда, когда что-то действительно становится повторяющимся, нечитаемым и т. д.

Все остальное — преждевременная оптимизация.

Django не заметит разницы при отправке формы.

fields = list(form)    
part1, part2 = fields[:4], fields[4:]


{% for field in part1 %}{{ field }}{% endfor %}
...
{% for field in part2 %}{{ field }}{% endfor %}
person Yuji 'Tomita' Tomita    schedule 13.12.2011
comment
список (форма) дает мне объект «DeclarativeFieldsMetaclass», который не повторяется. Почему вы используете «форму» в нижнем регистре в строке, которая читает список (форма)? Предположительно в представлении имя класса формы указано в верхнем регистре: «Форма». Спасибо. Я пытаюсь получить список полей формы. - person dlink; 15.12.2018

Я бы посоветовал вам написать собственный пользовательский шаблон. Возможно, ваш фильтр мог бы выглядеть так:

def show_part(form,section=1): 
    display = ''
    for id,field in enumerate(form):  
         if int(section) == 1 and id > 3:
             break
         elif int(section) == 2 and id < 3:
             continue
         display += '<tr><td>'+field.label_tag+'</td>'
         display += '<td>'+field+'</td></tr>'
    return display    

и используйте в своем шаблоне следующее:

<table>
    {{ form|show_part:"1" }}
</table>
<table>
    {{ form|show_part:"2" }}
</table>
person Gevious    schedule 13.12.2011

Поскольку форма представляет собой список, вы также можете использовать встроенный в Django фильтр шаблонов фрагментов: https://docs.djangoproject.com/en/1.3/ref/templates/builtins/#slice

Ваш пример станет:

    <table>
        {% for field in form|slice:":4" %}
        <tr>
            <td> {{ field.label_tag }} </td>
            <td> {{ field }} </td>
        </tr>
        {% endfor %}
    </table>
    .... Different code ....
    <table>
        {% for field in form|slice:"4:" %}
        <tr>
            <td> {{ field.label_tag }} </td>
            <td> {{ field }} </td>
        </tr>
        {% endfor %}
    </table>
person Ramon de Jesus    schedule 11.02.2014
comment
это работа? Я пробовал ваше решение, но не работает для меня. Но я улучшил ваш код после того, как нарезал {% for field in form.visible_fields|slice:":4" %}, и у меня сработало. - person Adiyat Mubarak; 25.04.2016

Вы почти у цели, если вы просто добавите

<table>
{% if forloop.counter <= 4 %}
... first four fields
{% else %}
... other fields
{% endif %}

Если вам нужны две разные таблицы, вы можете добавить:

{% if forloop.counter == 1 %}
<table>
{% endif %}

{% if forloop.last %}
</table>
{% endif %}

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

person c4urself    schedule 13.12.2011

Ответ короче, чем "Юдзи 'Томита' Томита"

Сделать список для формы на ваш взгляд:

context = {'form': list(form)}
return render(request, template, context)

и получить каждое поле в шаблоне |slice

{% for field in form|slice:":4" %}
    <tr>
        <td> {{ field.label_tag }} </td>
        <td> {{ field }} </td>
    </tr>
{% endfor %}
person Gajush    schedule 09.10.2014