Функция formset_factory
Функция formset_factory применяется для создания набора форм (formset), который представляет собой коллекцию однотипных форм. Она принимает базовую форму и возвращает класс FormSet, позволяющий управлять несколькими экземплярами этой формы одновременно. Аргументы передаются в виде ключевых параметров, где основным является форма, а дополнительные параметры управляют количеством форм, валидацией и другими аспектами работы набора.
Синтаксис
from django.forms import formset_factory
FormSetClass = formset_factory(form, **options)
Основные параметры
Функция принимает следующие параметры:
-
form- класс формы, на основе которого создаётся набор -
extra- количество дополнительных пустых форм (по умолчанию1) -
max_num- максимальное количество форм в наборе -
min_num- минимальное количество форм в наборе -
validate_min- флаг, включающий валидацию минимального количества форм -
validate_max- флаг, включающий валидацию максимального количества форм -
can_delete- разрешает удаление форм из набора -
can_order- позволяет изменять порядок форм
Пример . Базовое использование
Создадим простую форму для ввода данных о книге и набор форм для добавления нескольких книг:
from django import forms
from django.forms import formset_factory
class BookForm(forms.Form):
title = forms.CharField(max_length=100, label="Название")
author = forms.CharField(max_length=50, label="Автор")
year = forms.IntegerField(label="Год издания")
BookFormSet = formset_factory(BookForm, extra=3)
formset = BookFormSet()
for form in formset:
print(form.as_p())
Результат выполнения кода:
"<p><label for="id_form-0-title">Название:</label> <input type="text" name="form-0-title" maxlength="100" id="id_form-0-title"></p>
<p><label for="id_form-0-author">Автор:</label> <input type="text" name="form-0-author" maxlength="50" id="id_form-0-author"></p>
<p><label for="id_form-0-year">Год издания:</label> <input type="number" name="form-0-year" id="id_form-0-year"></p>
... (всего 3 формы)"
Пример . С обработкой данных
Рассмотрим пример обработки данных из набора форм, отправленных методом POST:
from django import forms
from django.forms import formset_factory
from django.shortcuts import render
class BookForm(forms.Form):
title = forms.CharField(max_length=100)
author = forms.CharField(max_length=50)
year = forms.IntegerField()
def add_books(request):
BookFormSet = formset_factory(BookForm, extra=2)
if request.method == 'POST':
formset = BookFormSet(request.POST)
if formset.is_valid():
for form in formset:
if form.cleaned_data:
title = form.cleaned_data['title']
author = form.cleaned_data['author']
year = form.cleaned_data['year']
print(f"Book: {title} by {author} ({year})")
else:
formset = BookFormSet()
return render(request, 'books.html', {'formset': formset})
Пример . С ограничением количества форм
Используем параметры max_num и min_num для ограничения количества форм:
from django import forms
from django.forms import formset_factory
class BookForm(forms.Form):
title = forms.CharField(max_length=100)
author = forms.CharField(max_length=50)
BookFormSet = formset_factory(
BookForm,
extra=2,
min_num=1,
max_num=5,
validate_min=True,
validate_max=True
)
formset = BookFormSet()
print(f"Total forms: {formset.total_form_count()}")
print(f"Initial forms: {formset.initial_form_count()}")
Результат выполнения кода:
"Total forms: 3"
"Initial forms: 1"
Пример . С удалением форм
Включим возможность удалять формы из набора с помощью параметра can_delete:
from django import forms
from django.forms import formset_factory
class BookForm(forms.Form):
title = forms.CharField(max_length=100)
author = forms.CharField(max_length=50)
BookFormSet = formset_factory(
BookForm,
extra=2,
can_delete=True
)
formset = BookFormSet()
for form in formset:
if form.can_delete:
print("Form has delete checkbox")
Пример . С изменением порядка форм
Используем параметр can_order для управления порядком форм:
from django import forms
from django.forms import formset_factory
class BookForm(forms.Form):
title = forms.CharField(max_length=100)
author = forms.CharField(max_length=50)
BookFormSet = formset_factory(
BookForm,
extra=3,
can_order=True
)
formset = BookFormSet()
for i, form in enumerate(formset):
order_field = form.fields.get('ORDER')
if order_field:
print(f"Form {i} has ORDER field")
Смотрите также
-
класс
Form,
который используется для создания базовых форм -
функция
modelformset_factory,
которая создаёт набор форм на основе модели -
функция
inlineformset_factory,
которая создаёт набор форм для связанных моделей -
метод
is_valid,
который проверяет валидность формы