Тег {% 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 отдельные формы.