summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorDavid Smith <smithdc@gmail.com>2020-04-30 08:34:53 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-06-05 12:01:32 +0200
commit433dd737f94b09043f64b873b0ac067b3f97364b (patch)
tree5c4dcf3c3c7d36008389d28f72c07f70726d65d0 /docs
parentb5aa9cb20f2d8fbffec3bc18aa31fca5f26d6f64 (diff)
Fixed #20347 -- Allowed customizing the maximum number of instantiated forms in formsets.
Co-authored-by: ethurgood <ethurgood@gmail.com>
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/forms/formsets.txt6
-rw-r--r--docs/ref/forms/models.txt16
-rw-r--r--docs/releases/3.2.txt5
-rw-r--r--docs/topics/forms/formsets.txt42
4 files changed, 58 insertions, 11 deletions
diff --git a/docs/ref/forms/formsets.txt b/docs/ref/forms/formsets.txt
index 778ae20db3..e145eeb103 100644
--- a/docs/ref/forms/formsets.txt
+++ b/docs/ref/forms/formsets.txt
@@ -11,8 +11,12 @@ Formset API reference. For introductory material about formsets, see the
``formset_factory``
===================
-.. function:: formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False, min_num=None, validate_min=False)
+.. function:: formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None, validate_max=False, min_num=None, validate_min=False, absolute_max=None)
Returns a ``FormSet`` class for the given ``form`` class.
See :doc:`formsets </topics/forms/formsets>` for example usage.
+
+ .. versionchanged:: 3.2
+
+ The ``absolute_max`` argument was added.
diff --git a/docs/ref/forms/models.txt b/docs/ref/forms/models.txt
index c5ddf99011..e18660b3c2 100644
--- a/docs/ref/forms/models.txt
+++ b/docs/ref/forms/models.txt
@@ -52,7 +52,7 @@ Model Form API reference. For introductory material about model forms, see the
``modelformset_factory``
========================
-.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None)
+.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None)
Returns a ``FormSet`` class for the given ``model`` class.
@@ -62,16 +62,20 @@ Model Form API reference. For introductory material about model forms, see the
through to :func:`~django.forms.models.modelform_factory`.
Arguments ``formset``, ``extra``, ``max_num``, ``can_order``,
- ``can_delete`` and ``validate_max`` are passed through to
- :func:`~django.forms.formsets.formset_factory`. See :doc:`formsets
+ ``can_delete``, ``validate_max``, and ``absolute_max`` are passed through
+ to :func:`~django.forms.formsets.formset_factory`. See :doc:`formsets
</topics/forms/formsets>` for details.
See :ref:`model-formsets` for example usage.
+ .. versionchanged:: 3.2
+
+ The ``absolute_max`` argument was added.
+
``inlineformset_factory``
=========================
-.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None)
+.. function:: inlineformset_factory(parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, widgets=None, validate_max=False, localized_fields=None, labels=None, help_texts=None, error_messages=None, min_num=None, validate_min=False, field_classes=None, absolute_max=None)
Returns an ``InlineFormSet`` using :func:`modelformset_factory` with
defaults of ``formset=``:class:`~django.forms.models.BaseInlineFormSet`,
@@ -81,3 +85,7 @@ Model Form API reference. For introductory material about model forms, see the
the ``parent_model``, you must specify a ``fk_name``.
See :ref:`inline-formsets` for example usage.
+
+ .. versionchanged:: 3.2
+
+ The ``absolute_max`` argument was added.
diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt
index 2ff09c69b0..03f485b224 100644
--- a/docs/releases/3.2.txt
+++ b/docs/releases/3.2.txt
@@ -136,7 +136,10 @@ File Uploads
Forms
~~~~~
-* ...
+* The new ``absolute_max`` argument for :func:`.formset_factory`,
+ :func:`.inlineformset_factory`, and :func:`.modelformset_factory` allows
+ customizing the maximum number of forms that can be instantiated when
+ supplying ``POST`` data. See :ref:`formsets-absolute-max` for more details.
Generic Views
~~~~~~~~~~~~~
diff --git a/docs/topics/forms/formsets.txt b/docs/topics/forms/formsets.txt
index 3b5775cabb..b3e696ed8c 100644
--- a/docs/topics/forms/formsets.txt
+++ b/docs/topics/forms/formsets.txt
@@ -126,6 +126,38 @@ affect validation. If ``validate_max=True`` is passed to the
:func:`~django.forms.formsets.formset_factory`, then ``max_num`` will affect
validation. See :ref:`validate_max`.
+.. _formsets-absolute-max:
+
+Limiting the maximum number of instantiated forms
+=================================================
+
+.. versionadded:: 3.2
+
+The ``absolute_max`` parameter to :func:`.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::
+
+ >>> from django.forms.formsets import formset_factory
+ >>> from myapp.forms import ArticleForm
+ >>> ArticleFormSet = formset_factory(ArticleForm, absolute_max=1500)
+ >>> data = {
+ ... 'form-TOTAL_FORMS': '1501',
+ ... 'form-INITIAL_FORMS': '0',
+ ... 'form-MAX_NUM_FORMS': '',
+ ... }
+ >>> formset = ArticleFormSet(data)
+ >>> len(formset.forms)
+ 1500
+ >>> formset.is_valid()
+ False
+ >>> formset.non_form_errors()
+ ['Please submit 1000 or fewer forms.']
+
+When ``absolute_max`` is None, it defaults to ``max_num + 1000``. (If
+``max_num`` is ``None``, it defaults to ``2000``).
+
+If ``absolute_max`` is less than ``max_num``, a ``ValueError`` will be raised.
+
Formset validation
==================
@@ -348,11 +380,11 @@ excessive.
.. note::
Regardless of ``validate_max``, if the number of forms in a data set
- exceeds ``max_num`` by more than 1000, then the form will fail to validate
- as if ``validate_max`` were set, and additionally only the first 1000
- forms above ``max_num`` will be validated. The remainder will be
- truncated entirely. This is to protect against memory exhaustion attacks
- using forged POST requests.
+ 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 :ref:`formsets-absolute-max`.
``validate_min``
----------------