<commit_before>.. _topics-forms-formsets:
.. _formsets:

Formsets
========

A formset is a layer of abstraction to working with multiple forms on the same
page. It can be best compared to a data grid. Let's say you have the following
form::

    >>> from django import forms
    >>> class ArticleForm(forms.Form):
    ...     title = forms.CharField()
    ...     pub_date = forms.DateField()

You might want to allow the user to create several articles at once. To create
a formset out of an ``ArticleForm`` you would do::

    >>> from django.forms.formsets import formset_factory
    >>> ArticleFormSet = formset_factory(ArticleForm)

You now have created a formset named ``ArticleFormSet``. The formset gives you
the ability to iterate over the forms in the formset and display them as you
would with a regular form::

    >>> formset = ArticleFormSet()
    >>> for form in formset.forms:
    ...     print form.as_table()
    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>

As you can see it only displayed one form. This is because by default the
``formset_factory`` defines one extra form. This can be controlled with the
``extra`` parameter::

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

Using initial data with a formset
---------------------------------

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. Lets take a look at an
example::

    >>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
    >>> formset = ArticleFormSet(initial=[
    ...     {'title': u'Django is now open source',
    ...      'pub_date': datetime.date.today()},
    ... ])

    >>> for form in formset.forms:
    ...     print form.as_table()
    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr>
    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr>
    <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr>
    <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr>
    <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
    <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>

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.

Limiting the maximum number of forms
------------------------------------

The ``max_num`` parameter to ``formset_factory`` gives you the ability to
force the maximum number of forms the formset will display::

    >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
    >>> formset = ArticleFormset()
    >>> for form in formset.forms:
    ...     print form.as_table()
    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>

A ``max_num`` value of ``0`` (the default) puts no limit on the number forms
displayed.

Formset validation
------------------

Validation with a formset is about identical to a regular ``Form``. There is
an ``is_valid`` method on the formset to provide a convenient way to validate
each form in the formset::

    >>> ArticleFormSet = formset_factory(ArticleForm)
    >>> formset = ArticleFormSet({})
    >>> formset.is_valid()
    True<commit_msg>Fixed #10795: added a link to model formsets docs from the formsets docs.<commit_after>.. _topics-forms-formsets:
.. _formsets:

Formsets
========

A formset is a layer of abstraction to working with multiple forms on the same
page. It can be best compared to a data grid. Let's say you have the following
form::

    >>> from django import forms
    >>> class ArticleForm(forms.Form):
    ...     title = forms.CharField()
    ...     pub_date = forms.DateField()

You might want to allow the user to create several articles at once. To create
a formset out of an ``ArticleForm`` you would do::

    >>> from django.forms.formsets import formset_factory
    >>> ArticleFormSet = formset_factory(ArticleForm)

You now have created a formset named ``ArticleFormSet``. The formset gives you
the ability to iterate over the forms in the formset and display them as you
would with a regular form::

    >>> formset = ArticleFormSet()
    >>> for form in formset.forms:
    ...     print form.as_table()
    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>

As you can see it only displayed one form. This is because by default the
``formset_factory`` defines one extra form. This can be controlled with the
``extra`` parameter::

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

Using initial data with a formset
---------------------------------

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. Lets take a look at an
example::

    >>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
    >>> formset = ArticleFormSet(initial=[
    ...     {'title': u'Django is now open source',
    ...      'pub_date': datetime.date.today()},
    ... ])

    >>> for form in formset.forms:
    ...     print form.as_table()
    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Django is now open source" id="id_form-0-title" /></td></tr>
    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" value="2008-05-12" id="id_form-0-pub_date" /></td></tr>
    <tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" id="id_form-1-title" /></td></tr>
    <tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" id="id_form-1-pub_date" /></td></tr>
    <tr><th><label for="id_form-2-title">Title:</label></th><td><input type="text" name="form-2-title" id="id_form-2-title" /></td></tr>
    <tr><th><label for="id_form-2-pub_date">Pub date:</label></th><td><input type="text" name="form-2-pub_date" id="id_form-2-pub_date" /></td></tr>

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.

.. seealso::

    :ref:`Creating formsets from models with model formsets <model-formsets>`.

Limiting the maximum number of forms
------------------------------------

The ``max_num`` parameter to ``formset_factory`` gives you the ability to
force the maximum number of forms the formset will display::

    >>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
    >>> formset = ArticleFormset()
    >>> for form in formset.forms:
    ...     print form.as_table()
    <tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" id="id_form-0-title" /></td></tr>
    <tr><th><label for="id_form-0-pub_date">Pub date:</label></th><td><input type="text" name="form-0-pub_date" id="id_form-0-pub_date" /></td></tr>

A ``max_num`` value of ``0`` (the default) puts no limit on the number forms
displayed.

Formset validation
------------------

Validation with a formset is about identical to a regular ``Form``. There is
an ``is_valid`` method on the formset to provide a convenient way to validate
each form in the formset::

    >>> ArticleFormSet = formset_factory(ArticleForm)
    >>> formset = ArticleFormSet({})
    >>> formset.is_valid()
    True
{'fraction_non_alphanumeric': 0.1745368278355174, 'fraction_numerical': 0.010280162675101671, 'mean_word_length': 3.7342245989304814, 'pattern_counts': {'":': 0, '<': 184, '<?xml version=': 0, '>': 280, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4798475', 'n_tokens_mistral': 2822, 'n_tokens_neox': 2736, 'n_words': 882}