33
33
As you can see it only displayed one empty form. The number of empty forms
34
34
that is displayed is controlled by the ``extra`` parameter. By default,
35
``formset_factory`` defines one extra form; the following example will
36
display two blank forms::
35
:func:`~django.forms.formsets.formset_factory` defines one extra form; the
36
following example will display two blank forms::
38
38
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
56
56
number of forms it generates from the initial data. Lets take a look at an
60
>>> from django.forms.formsets import formset_factory
61
>>> from myapp.forms import ArticleForm
59
62
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
60
63
>>> formset = ArticleFormSet(initial=[
61
64
... {'title': u'Django is now open source',
84
87
Limiting the maximum number of forms
85
88
------------------------------------
87
The ``max_num`` parameter to ``formset_factory`` gives you the ability to
88
limit the maximum number of empty forms the formset will display::
90
The ``max_num`` parameter to :func:`~django.forms.formsets.formset_factory`
91
gives you the ability to limit the maximum number of empty forms the formset
94
>>> from django.forms.formsets import formset_factory
95
>>> from myapp.forms import ArticleForm
90
96
>>> ArticleFormSet = formset_factory(ArticleForm, extra=2, max_num=1)
91
>>> formset = ArticleFormset()
97
>>> formset = ArticleFormSet()
92
98
>>> for form in formset:
93
99
... print(form.as_table())
94
100
<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>
101
107
A ``max_num`` value of ``None`` (the default) puts a high limit on the number
102
108
of forms displayed (1000). In practice this is equivalent to no limit.
110
If the number of forms in the initial data exceeds ``max_num``, all initial
111
data forms will be displayed regardless. (No extra forms will be displayed.)
113
By default, ``max_num`` only affects how many forms are displayed and does not
114
affect validation. If ``validate_max=True`` is passed to the
115
:func:`~django.forms.formsets.formset_factory`, then ``max_num`` will affect
116
validation. See :ref:`validate_max`.
118
.. versionchanged:: 1.6
120
The ``validate_max`` parameter was added to
121
:func:`~django.forms.formsets.formset_factory`. Also, the behavior of
122
``FormSet`` was brought in line with that of ``ModelFormSet`` so that it
123
displays initial data regardless of ``max_num``.
104
125
Formset validation
105
126
------------------
141
164
forms in the formset. Validation was performed for each of the two forms, and
142
165
the expected error message appears for the second item.
144
.. versionadded:: 1.4
167
.. currentmodule:: django.forms.formsets.BaseFormSet
169
.. method:: total_error_count(self)
171
.. versionadded:: 1.6
173
To check how many errors there are in the formset, we can use the
174
``total_error_count`` method::
176
>>> # Using the previous example
178
[{}, {'pub_date': [u'This field is required.']}]
179
>>> len(formset.errors)
181
>>> formset.total_error_count()
146
184
We can also check if form data differs from the initial data (i.e. the form was
147
185
sent without any data)::
253
292
have been called. The errors will be found using the ``non_form_errors()``
254
293
method on the formset.
297
Validating the number of forms in a formset
298
-------------------------------------------
300
If ``validate_max=True`` is passed to
301
:func:`~django.forms.formsets.formset_factory`, validation will also check
302
that the number of forms in the data set, minus those marked for
303
deletion, is less than or equal to ``max_num``.
305
>>> from django.forms.formsets import formset_factory
306
>>> from myapp.forms import ArticleForm
307
>>> ArticleFormSet = formset_factory(ArticleForm, max_num=1, validate_max=True)
309
... 'form-TOTAL_FORMS': u'2',
310
... 'form-INITIAL_FORMS': u'0',
311
... 'form-MAX_NUM_FORMS': u'',
312
... 'form-0-title': u'Test',
313
... 'form-0-pub_date': u'1904-06-16',
314
... 'form-1-title': u'Test 2',
315
... 'form-1-pub_date': u'1912-06-23',
317
>>> formset = ArticleFormSet(data)
318
>>> formset.is_valid()
322
>>> formset.non_form_errors()
323
[u'Please submit 1 or fewer forms.']
325
``validate_max=True`` validates against ``max_num`` strictly even if
326
``max_num`` was exceeded because the amount of initial data supplied was
329
Applications which need more customizable validation of the number of forms
330
should use custom formset validation.
334
Regardless of ``validate_max``, if the number of forms in a data set
335
exceeds ``max_num`` by more than 1000, then the form will fail to validate
336
as if ``validate_max`` were set, and additionally only the first 1000
337
forms above ``max_num`` will be validated. The remainder will be
338
truncated entirely. This is to protect against memory exhaustion attacks
339
using forged POST requests.
341
.. versionchanged:: 1.6
343
The ``validate_max`` parameter was added to
344
:func:`~django.forms.formsets.formset_factory`.
256
346
Dealing with ordering and deletion of forms
257
347
-------------------------------------------
259
Common use cases with a formset is dealing with ordering and deletion of the
260
form instances. This has been dealt with for you. The ``formset_factory``
261
provides two optional parameters ``can_order`` and ``can_delete`` that will do
262
the extra work of adding the extra fields and providing simpler ways of
263
getting to that data.
349
The :func:`~django.forms.formsets.formset_factory` provides two optional
350
parameters ``can_order`` and ``can_delete`` to help with ordering of forms in
351
formsets and deletion of forms from a formset.
270
358
Lets you create a formset with the ability to order::
360
>>> from django.forms.formsets import formset_factory
361
>>> from myapp.forms import ArticleForm
272
362
>>> ArticleFormSet = formset_factory(ArticleForm, can_order=True)
273
363
>>> formset = ArticleFormSet(initial=[
274
364
... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
278
368
... print(form.as_table())
279
369
<tr><th><label for="id_form-0-title">Title:</label></th><td><input type="text" name="form-0-title" value="Article #1" id="id_form-0-title" /></td></tr>
280
370
<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-10" id="id_form-0-pub_date" /></td></tr>
281
<tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="text" name="form-0-ORDER" value="1" id="id_form-0-ORDER" /></td></tr>
371
<tr><th><label for="id_form-0-ORDER">Order:</label></th><td><input type="number" name="form-0-ORDER" value="1" id="id_form-0-ORDER" /></td></tr>
282
372
<tr><th><label for="id_form-1-title">Title:</label></th><td><input type="text" name="form-1-title" value="Article #2" id="id_form-1-title" /></td></tr>
283
373
<tr><th><label for="id_form-1-pub_date">Pub date:</label></th><td><input type="text" name="form-1-pub_date" value="2008-05-11" id="id_form-1-pub_date" /></td></tr>
284
<tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="text" name="form-1-ORDER" value="2" id="id_form-1-ORDER" /></td></tr>
374
<tr><th><label for="id_form-1-ORDER">Order:</label></th><td><input type="number" name="form-1-ORDER" value="2" id="id_form-1-ORDER" /></td></tr>
285
375
<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>
286
376
<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>
287
<tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="text" name="form-2-ORDER" id="id_form-2-ORDER" /></td></tr>
377
<tr><th><label for="id_form-2-ORDER">Order:</label></th><td><input type="number" name="form-2-ORDER" id="id_form-2-ORDER" /></td></tr>
289
379
This adds an additional field to each form. This new field is named ``ORDER``
290
380
and is an ``forms.IntegerField``. For the forms that came from the initial
326
416
Lets you create a formset with the ability to select forms for deletion::
418
>>> from django.forms.formsets import formset_factory
419
>>> from myapp.forms import ArticleForm
328
420
>>> ArticleFormSet = formset_factory(ArticleForm, can_delete=True)
329
421
>>> formset = ArticleFormSet(initial=[
330
422
... {'title': u'Article #1', 'pub_date': datetime.date(2008, 5, 10)},
384
476
can simply override this method to add your own fields or even redefine the
385
477
default fields/attributes of the order and deletion fields::
479
>>> from django.forms.formsets import BaseFormSet
480
>>> from django.forms.formsets import formset_factory
481
>>> from myapp.forms import ArticleForm
387
482
>>> class BaseArticleFormSet(BaseFormSet):
388
483
... def add_fields(self, form, index):
389
484
... super(BaseArticleFormSet, self).add_fields(form, index)