Тег {% crispy %} с наборами форм

Тег {% crispy %} также поддерживает рендеринг наборов форм, все виды наборов форм Django: наборы форм, модельные наборы форм и инлайн наборы форм. В этом разделе предполагается, что вы знакомы с предыдущими концепциями crispy-forms в документации, такими как FormHelper, как установить атрибуты FormHelper или отрисовать простую форму с помощью тега {% crispy %}.

Формсеты

В задачи этой документации не входит подробное объяснение работы наборов форм, для этого вам следует ознакомиться с Django official formset docs. Давайте начнем создавать набор форм, используя предыдущую форму ExampleForm:

from django.forms.models import formset_factory

ExampleFormSet = formset_factory(ExampleForm, extra=3)
formset = ExampleFormSet()

Вот как можно отобразить набор форм, используя рендеринг по умолчанию, без макетов и помощников формы:

{% crispy formset %}

Конечно, вы все равно можете использовать хелпер, иначе в этом не было бы ничего хрустящего. При использовании FormHelper с набором форм по сравнению с использованием его с формой, основное различие заключается в том, что атрибуты хелпера применяются к структуре формы, в то время как макет применяется к формам набора форм. Давайте создадим хелпер для нашего ExampleFormSet:

class ExampleFormSetHelper(FormHelper):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.form_method = 'post'
        self.layout = Layout(
            'favorite_color',
            'favorite_food',
        )
        self.render_required_fields = True

Этот помощник довольно прост в использовании. Мы хотим, чтобы наша форма использовала метод POST, и мы хотим, чтобы favorite_color было первым полем, затем favorite_food и, наконец, мы говорим crispy выводить все необходимые поля после. Давайте начнем использовать это, при использовании тега {% crispy %} в шаблоне есть одно основное различие при рендеринге наборов форм против форм, в этом случае вам нужно явно указать помощника.

Это было бы частью гипотетической функции view:

formset = ExampleFormSet()
helper = ExampleFormSetHelper()
return render(request, 'template.html', {'formset': formset, 'helper': helper})

Тогда в template.html вам нужно будет сделать:

{% crispy formset helper %}

Существует два способа добавления кнопок отправки в набор форм. Используя метод FormHelper.add_input:

helper.add_input(Submit("submit", "Save"))

Или вы можете установить FormHelper.form_tag в False и управлять внешней структурой набора форм по своему желанию, написав скучный HTML:

<form action="{% url 'save_formset' %}" method="POST">
    {% crispy formset helper %}
    <div class="form-actions">
        <input type="submit" name="submit" value="Save" class="btn btn-primary" id="submit-save">
    </div>
</form>

Наконец, модельные наборы форм и встроенные наборы форм отображаются точно так же, как и наборы форм, разница лишь в том, как вы создаете их в коде Django.

Дополнительный контекст

Рендеринг любого типа набора форм с помощью crispy вводит некоторый дополнительный контекст в рендеринг макета, чтобы вы могли делать такие вещи, как:

HTML("{% if forloop.first %}Message displayed only in the first form of a formset forms list{% endif %}",
Fieldset("Item {{ forloop.counter }}", 'field-1', [...])

По сути, вы можете получить доступ к узлу forloop Django, как если бы вы рендерили свои формы с помощью цикла for.

Пользовательские шаблоны и табличные инлайн-наборы форм

Шаблон форм по умолчанию отображает форму вашего набора форм с помощью div’ов, но многие люди предпочитают таблицы для наборов форм. Не волнуйтесь, crispy-forms позаботится об этом. FormHelper имеет атрибут template, который может быть использован для указания пользовательского шаблона для отображения формы или набора форм, в данном случае набора форм. Очевидно, что когда мы указываем атрибут template, мы делаем этот помощник используемым только с формами или наборами форм.

Имя шаблона для использования - table_inline_formset.html, и вы используете его, делая:

helper.template = 'bootstrap/table_inline_formset.html'

Самое приятное, что если этот шаблон не делает того, что вам нужно, вы можете скопировать его в свою папку с шаблонами, настроить его и затем связать свой помощник с альтернативной версией. Если вы считаете, что то, чего не хватает вам, будет полезно другим, то, пожалуйста, отправьте запрос на исправление на github.

Предупреждение

В настоящее время этот шаблон не учитывает заданный вами макет и работает только с пакетом шаблонов bootstrap.

Формы с различными макетами

По умолчанию рендеринг набора форм crispy-forms разделяет один и тот же макет между всеми формами набора. Это происходит в 99% случаев. Но, возможно, вы хотите, чтобы формы вашего набора форм отображались в разных макетах, чего нельзя добиться с помощью дополнительного контекста, для этого вам придется создать и использовать пользовательский шаблон. Скорее всего, вы захотите сделать следующее:

{{ formset.management_form|crispy }}
{% for form in formset %}
    {% crispy form %}
{% endfor %}

Где каждый form имеет атрибут helper, из которого crispy будет брать макет. В вашем представлении вам нужно будет изменить макет или использовать другой help для каждой формы набора форм. Убедитесь, что атрибут form_tag установлен на False, иначе вы получите 3 отдельные формы.

Вернуться на верх