diff options
| author | David Smith <smithdc@gmail.com> | 2020-04-30 08:34:53 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-06-05 12:01:32 +0200 |
| commit | 433dd737f94b09043f64b873b0ac067b3f97364b (patch) | |
| tree | 5c4dcf3c3c7d36008389d28f72c07f70726d65d0 /docs | |
| parent | b5aa9cb20f2d8fbffec3bc18aa31fca5f26d6f64 (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.txt | 6 | ||||
| -rw-r--r-- | docs/ref/forms/models.txt | 16 | ||||
| -rw-r--r-- | docs/releases/3.2.txt | 5 | ||||
| -rw-r--r-- | docs/topics/forms/formsets.txt | 42 |
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`` ---------------- |
