summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/contenttypes/forms.py4
-rw-r--r--docs/ref/contrib/contenttypes.txt6
-rw-r--r--docs/releases/3.2.txt5
-rw-r--r--tests/generic_relations/test_forms.py34
4 files changed, 46 insertions, 3 deletions
diff --git a/django/contrib/contenttypes/forms.py b/django/contrib/contenttypes/forms.py
index de1fcaf4bb..ce1c361b6c 100644
--- a/django/contrib/contenttypes/forms.py
+++ b/django/contrib/contenttypes/forms.py
@@ -56,7 +56,8 @@ def generic_inlineformset_factory(model, form=ModelForm,
extra=3, can_order=False, can_delete=True,
max_num=None, formfield_callback=None,
validate_max=False, for_concrete_model=True,
- min_num=None, validate_min=False):
+ min_num=None, validate_min=False,
+ absolute_max=None):
"""
Return a ``GenericInlineFormSet`` for the given kwargs.
@@ -75,6 +76,7 @@ def generic_inlineformset_factory(model, form=ModelForm,
formset=formset, extra=extra, can_delete=can_delete,
can_order=can_order, fields=fields, exclude=exclude, max_num=max_num,
validate_max=validate_max, min_num=min_num, validate_min=validate_min,
+ absolute_max=absolute_max,
)
FormSet.ct_field = ct_field
FormSet.ct_fk_field = fk_field
diff --git a/docs/ref/contrib/contenttypes.txt b/docs/ref/contrib/contenttypes.txt
index 66dbfe45ef..6cc0033132 100644
--- a/docs/ref/contrib/contenttypes.txt
+++ b/docs/ref/contrib/contenttypes.txt
@@ -466,7 +466,7 @@ The :mod:`django.contrib.contenttypes.forms` module provides:
.. class:: BaseGenericInlineFormSet
-.. function:: generic_inlineformset_factory(model, form=ModelForm, formset=BaseGenericInlineFormSet, ct_field="content_type", fk_field="object_id", fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, validate_max=False, for_concrete_model=True, min_num=None, validate_min=False)
+.. function:: generic_inlineformset_factory(model, form=ModelForm, formset=BaseGenericInlineFormSet, ct_field="content_type", fk_field="object_id", fields=None, exclude=None, extra=3, can_order=False, can_delete=True, max_num=None, formfield_callback=None, validate_max=False, for_concrete_model=True, min_num=None, validate_min=False, absolute_max=None)
Returns a ``GenericInlineFormSet`` using
:func:`~django.forms.models.modelformset_factory`.
@@ -481,6 +481,10 @@ The :mod:`django.contrib.contenttypes.forms` module provides:
:class:`~django.contrib.contenttypes.fields.GenericForeignKey.for_concrete_model`
argument on ``GenericForeignKey``.
+ .. versionchanged:: 3.2
+
+ The ``absolute_max`` argument was added.
+
.. module:: django.contrib.contenttypes.admin
Generic relations in admin
diff --git a/docs/releases/3.2.txt b/docs/releases/3.2.txt
index 65a2e6dc99..1acea66cff 100644
--- a/docs/releases/3.2.txt
+++ b/docs/releases/3.2.txt
@@ -85,7 +85,10 @@ Minor features
:mod:`django.contrib.contenttypes`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* ...
+* The new ``absolute_max`` argument for
+ :func:`~django.contrib.contenttypes.forms.generic_inlineformset_factory`
+ allows customizing the maximum number of forms that can be instantiated when
+ supplying ``POST`` data. See :ref:`formsets-absolute-max` for more details.
:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/tests/generic_relations/test_forms.py b/tests/generic_relations/test_forms.py
index 4b94f24531..1a05681711 100644
--- a/tests/generic_relations/test_forms.py
+++ b/tests/generic_relations/test_forms.py
@@ -237,3 +237,37 @@ id="id_generic_relations-taggeditem-content_type-object_id-1-id"></p>""" % tagge
self.assertEqual([tag.tag for tag in tags], ['hunts', 'roars'])
hunts, roars = tags
self.assertSequenceEqual(lion.tags.order_by('tag'), [hairy, hunts, roars, yellow])
+
+ def test_absolute_max(self):
+ GenericFormSet = generic_inlineformset_factory(TaggedItem, absolute_max=1500)
+ data = {
+ 'form-TOTAL_FORMS': '1501',
+ 'form-INITIAL_FORMS': '0',
+ 'form-MAX_NUM_FORMS': '0',
+ }
+ formset = GenericFormSet(data=data, prefix='form')
+ self.assertIs(formset.is_valid(), False)
+ self.assertEqual(len(formset.forms), 1500)
+ self.assertEqual(
+ formset.non_form_errors(),
+ ['Please submit 1000 or fewer forms.'],
+ )
+
+ def test_absolute_max_with_max_num(self):
+ GenericFormSet = generic_inlineformset_factory(
+ TaggedItem,
+ max_num=20,
+ absolute_max=100,
+ )
+ data = {
+ 'form-TOTAL_FORMS': '101',
+ 'form-INITIAL_FORMS': '0',
+ 'form-MAX_NUM_FORMS': '0',
+ }
+ formset = GenericFormSet(data=data, prefix='form')
+ self.assertIs(formset.is_valid(), False)
+ self.assertEqual(len(formset.forms), 100)
+ self.assertEqual(
+ formset.non_form_errors(),
+ ['Please submit 20 or fewer forms.'],
+ )