~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to docs/topics/forms/formsets.txt

  • Committer: Package Import Robot
  • Author(s): Luke Faraone
  • Date: 2013-11-07 15:33:49 UTC
  • mfrom: (1.3.12)
  • Revision ID: package-import@ubuntu.com-20131107153349-e31sc149l2szs3jb
Tags: 1.6-1
* New upstream version. Closes: #557474, #724637.
* python-django now also suggests the installation of ipython,
  bpython, python-django-doc, and libgdal1.
  Closes: #636511, #686333, #704203
* Set package maintainer to Debian Python Modules Team.
* Bump standards version to 3.9.5, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
 
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::
37
37
 
38
38
    >>> ArticleFormSet = formset_factory(ArticleForm, extra=2)
39
39
 
56
56
number of forms it generates from the initial data. Lets take a look at an
57
57
example::
58
58
 
 
59
    >>> import datetime
 
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
------------------------------------
86
89
 
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
 
92
will display::
89
93
 
 
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.
103
109
 
 
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.)
 
112
 
 
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`.
 
117
 
 
118
.. versionchanged:: 1.6
 
119
 
 
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``.
 
124
 
104
125
Formset validation
105
126
------------------
106
127
 
108
129
an ``is_valid`` method on the formset to provide a convenient way to validate
109
130
all forms in the formset::
110
131
 
 
132
    >>> from django.forms.formsets import formset_factory
 
133
    >>> from myapp.forms import ArticleForm
111
134
    >>> ArticleFormSet = formset_factory(ArticleForm)
112
135
    >>> data = {
113
136
    ...     'form-TOTAL_FORMS': u'1',
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.
143
166
 
144
 
.. versionadded:: 1.4
 
167
.. currentmodule:: django.forms.formsets.BaseFormSet
 
168
 
 
169
.. method:: total_error_count(self)
 
170
 
 
171
.. versionadded:: 1.6
 
172
 
 
173
To check how many errors there are in the formset, we can use the
 
174
``total_error_count`` method::
 
175
 
 
176
    >>> # Using the previous example
 
177
    >>> formset.errors
 
178
    [{}, {'pub_date': [u'This field is required.']}]
 
179
    >>> len(formset.errors)
 
180
    2
 
181
    >>> formset.total_error_count()
 
182
    1
145
183
 
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)::
216
254
is where you define your own validation that works at the formset level::
217
255
 
218
256
    >>> from django.forms.formsets import BaseFormSet
 
257
    >>> from django.forms.formsets import formset_factory
 
258
    >>> from myapp.forms import ArticleForm
219
259
 
220
260
    >>> class BaseArticleFormSet(BaseFormSet):
221
261
    ...     def clean(self):
224
264
    ...             # Don't bother validating the formset unless each form is valid on its own
225
265
    ...             return
226
266
    ...         titles = []
227
 
    ...         for i in range(0, self.total_form_count()):
228
 
    ...             form = self.forms[i]
 
267
    ...         for form in self.forms:
229
268
    ...             title = form.cleaned_data['title']
230
269
    ...             if title in titles:
231
270
    ...                 raise forms.ValidationError("Articles in a set must have distinct titles.")
253
292
have been called. The errors will be found using the ``non_form_errors()``
254
293
method on the formset.
255
294
 
 
295
.. _validate_max:
 
296
 
 
297
Validating the number of forms in a formset
 
298
-------------------------------------------
 
299
 
 
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``.
 
304
 
 
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)
 
308
    >>> data = {
 
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',
 
316
    ... }
 
317
    >>> formset = ArticleFormSet(data)
 
318
    >>> formset.is_valid()
 
319
    False
 
320
    >>> formset.errors
 
321
    [{}, {}]
 
322
    >>> formset.non_form_errors()
 
323
    [u'Please submit 1 or fewer forms.']
 
324
 
 
325
``validate_max=True`` validates against ``max_num`` strictly even if
 
326
``max_num`` was exceeded because the amount of initial data supplied was
 
327
excessive.
 
328
 
 
329
Applications which need more customizable validation of the number of forms
 
330
should use custom formset validation.
 
331
 
 
332
.. note::
 
333
 
 
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.
 
340
 
 
341
.. versionchanged:: 1.6
 
342
 
 
343
   The ``validate_max`` parameter was added to
 
344
   :func:`~django.forms.formsets.formset_factory`.
 
345
 
256
346
Dealing with ordering and deletion of forms
257
347
-------------------------------------------
258
348
 
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.
264
352
 
265
353
``can_order``
266
354
~~~~~~~~~~~~~
269
357
 
270
358
Lets you create a formset with the ability to order::
271
359
 
 
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>
288
378
 
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
325
415
 
326
416
Lets you create a formset with the ability to select forms for deletion::
327
417
 
 
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::
386
478
 
 
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)
406
501
 
407
502
.. code-block:: python
408
503
 
 
504
    from django.forms.formsets import formset_factory
 
505
    from django.shortcuts import render_to_response
 
506
    from myapp.forms import ArticleForm
 
507
 
409
508
    def manage_articles(request):
410
509
        ArticleFormSet = formset_factory(ArticleForm)
411
510
        if request.method == 'POST':
481
580
 
482
581
.. code-block:: python
483
582
 
 
583
    from django.forms.formsets import formset_factory
 
584
    from django.shortcuts import render_to_response
 
585
    from myapp.forms import ArticleForm, BookForm
 
586
 
484
587
    def manage_articles(request):
485
588
        ArticleFormSet = formset_factory(ArticleForm)
486
589
        BookFormSet = formset_factory(BookForm)