As you can see it only displayed one empty form. The number of empty forms
that is displayed is controlled by the extra parameter. By default,
formset_factory() defines one extra form; the
following example will create a formset class to display two blank forms:

>>> ArticleFormSet=formset_factory(ArticleForm,extra=2)

Iterating over a formset will render the forms in the order they were
created. You can change this order by providing an alternate implementation for
the __iter__() method.

Formsets can also be indexed into, which returns the corresponding form. If you
override __iter__, you will need to also override __getitem__ to have
matching behavior.

Initial data is what drives the main usability of a formset. As shown above
you can define the number of extra forms. What this means is that you are
telling the formset how many additional forms to show in addition to the
number of forms it generates from the initial data. Let’s take a look at an
example:

There are now a total of three forms showing above. One for the initial data
that was passed in and two extra forms. Also note that we are passing in a
list of dictionaries as the initial data.

If you use an initial for displaying a formset, you should pass the same
initial when processing that formset’s submission so that the formset can
detect which forms were changed by the user. For example, you might have
something like: ArticleFormSet(request.POST,initial=[...]).

If the value of max_num is greater than the number of existing items in the
initial data, up to extra additional blank forms will be added to the
formset, so long as the total number of forms does not exceed max_num. For
example, if extra=2 and max_num=2 and the formset is initialized with
one initial item, a form for the initial item and one blank form will be
displayed.

If the number of items in the initial data exceeds max_num, all initial
data forms will be displayed regardless of the value of max_num and no
extra forms will be displayed. For example, if extra=3 and max_num=1
and the formset is initialized with two initial items, two forms with the
initial data will be displayed.

A max_num value of None (the default) puts a high limit on the number
of forms displayed (1000). In practice this is equivalent to no limit.

By default, max_num only affects how many forms are displayed and does not
affect validation. If validate_max=True is passed to the
formset_factory(), then max_num will affect
validation. See validate_max.

The absolute_max parameter to formset_factory() allows limiting the
number of forms that can be instantiated when supplying POST data. This
protects against memory exhaustion attacks using forged POST requests:

As we can see, formset.errors is a list whose entries correspond to the
forms in the formset. Validation was performed for each of the two forms, and
the expected error message appears for the second item.

Just like when using a normal Form, each field in a formset’s forms may
include HTML attributes such as maxlength for browser validation. However,
form fields of formsets won’t include the required attribute as that
validation may be incorrect when adding and deleting forms.

You may have noticed the additional data (form-TOTAL_FORMS,
form-INITIAL_FORMS and form-MAX_NUM_FORMS) that was required
in the formset’s data above. This data is required for the
ManagementForm. This form is used by the formset to manage the
collection of forms contained in the formset. If you don’t provide
this management data, an exception will be raised:

It is used to keep track of how many form instances are being displayed. If
you are adding new forms via JavaScript, you should increment the count fields
in this form as well. On the other hand, if you are using JavaScript to allow
deletion of existing objects, then you need to ensure the ones being removed
are properly marked for deletion by including form-#-DELETE in the POST
data. It is expected that all forms are present in the POST data regardless.

The management form is available as an attribute of the formset
itself. When rendering a formset in a template, you can include all
the management data by rendering {{my_formset.management_form}}
(substituting the name of your formset as appropriate).

BaseFormSet has a couple of methods that are closely related to the
ManagementForm, total_form_count and initial_form_count.

total_form_count returns the total number of forms in this formset.
initial_form_count returns the number of forms in the formset that were
pre-filled, and is also used to determine how many forms are required. You
will probably never need to override either of these methods, so please be
sure you understand what they do before doing so.

Django provides a couple ways to validate the minimum or maximum number of
submitted forms. Applications which need more customizable validation of the
number of forms should use custom formset validation.

validate_max=True validates against max_num strictly even if
max_num was exceeded because the amount of initial data supplied was
excessive.

Note

Regardless of validate_max, if the number of forms in a data set
exceeds absolute_max, then the form will fail to validate as if
validate_max were set, and additionally only the first absolute_max
forms will be validated. The remainder will be truncated entirely. This is
to protect against memory exhaustion attacks using forged POST requests.
See Limiting the maximum number of instantiated forms.

This adds an additional field to each form. This new field is named ORDER
and is an forms.IntegerField. For the forms that came from the initial
data it automatically assigned them a numeric value. Let’s look at what will
happen when the user changes these values:

On the other hand, if you are using a plain FormSet, it’s up to you to
handle formset.deleted_forms, perhaps in your formset’s save() method,
as there’s no general notion of what it means to delete a form.

If you need to add additional fields to the formset this can be easily
accomplished. The formset base class provides an add_fields method. You
can override this method to add your own fields or even redefine the default
fields/attributes of the order and deletion fields:

The form_kwargs may also depend on the specific form instance. The formset
base class provides a get_form_kwargs method. The method takes a single
argument - the index of the form in the formset. The index is None for the
empty_form:

Using a formset inside a view is not very different from using a regular
Form class. The only thing you will want to be aware of is making sure to
use the management form inside the template. Let’s look at a sample view:

fromdjango.formsimportformset_factoryfromdjango.shortcutsimportrenderfrommyapp.formsimportArticleFormdefmanage_articles(request):ArticleFormSet=formset_factory(ArticleForm)ifrequest.method=='POST':formset=ArticleFormSet(request.POST,request.FILES)ifformset.is_valid():# do something with the formset.cleaned_datapasselse:formset=ArticleFormSet()returnrender(request,'manage_articles.html',{'formset':formset})

You are able to use more than one formset in a view if you like. Formsets
borrow much of its behavior from forms. With that said you are able to use
prefix to prefix formset form field names with a given value to allow
more than one formset to be sent to a view without name clashing. Let’s take
a look at how this might be accomplished:

fromdjango.formsimportformset_factoryfromdjango.shortcutsimportrenderfrommyapp.formsimportArticleForm,BookFormdefmanage_articles(request):ArticleFormSet=formset_factory(ArticleForm)BookFormSet=formset_factory(BookForm)ifrequest.method=='POST':article_formset=ArticleFormSet(request.POST,request.FILES,prefix='articles')book_formset=BookFormSet(request.POST,request.FILES,prefix='books')ifarticle_formset.is_valid()andbook_formset.is_valid():# do something with the cleaned_data on the formsets.passelse:article_formset=ArticleFormSet(prefix='articles')book_formset=BookFormSet(prefix='books')returnrender(request,'manage_articles.html',{'article_formset':article_formset,'book_formset':book_formset,})

You would then render the formsets as normal. It is important to point out
that you need to pass prefix on both the POST and non-POST cases so that
it is rendered and processed correctly.

Each formset’s prefix replaces the default form
prefix that’s added to each field’s name and id HTML attributes.