summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomer Chachamu <tomer@festicket.com>2017-11-24 15:48:15 +0000
committerTim Graham <timograham@gmail.com>2017-12-30 11:38:11 -0500
commit9bc4d90d1a8c4d1dee54115a0995a7b6fca8635b (patch)
treef83f4124172f350a31c1777d7bfa24bffacd4b3c
parentda82939e5a31dea21a4f4d5085dfcd449fcbed3a (diff)
Fixed #14642 -- Fixed generic inline formsets crash when using save_as_new=True.
-rw-r--r--django/contrib/contenttypes/forms.py8
-rw-r--r--tests/generic_relations/test_forms.py37
2 files changed, 44 insertions, 1 deletions
diff --git a/django/contrib/contenttypes/forms.py b/django/contrib/contenttypes/forms.py
index d4c3313240..de1fcaf4bb 100644
--- a/django/contrib/contenttypes/forms.py
+++ b/django/contrib/contenttypes/forms.py
@@ -9,7 +9,7 @@ class BaseGenericInlineFormSet(BaseModelFormSet):
A formset for generic inline objects to a parent.
"""
- def __init__(self, data=None, files=None, instance=None, save_as_new=None,
+ def __init__(self, data=None, files=None, instance=None, save_as_new=False,
prefix=None, queryset=None, **kwargs):
opts = self.model._meta
self.instance = instance
@@ -17,6 +17,7 @@ class BaseGenericInlineFormSet(BaseModelFormSet):
opts.app_label + '-' + opts.model_name + '-' +
self.ct_field.name + '-' + self.ct_fk_field.name
)
+ self.save_as_new = save_as_new
if self.instance is None or self.instance.pk is None:
qs = self.model._default_manager.none()
else:
@@ -29,6 +30,11 @@ class BaseGenericInlineFormSet(BaseModelFormSet):
})
super().__init__(queryset=qs, data=data, files=files, prefix=prefix, **kwargs)
+ def initial_form_count(self):
+ if self.save_as_new:
+ return 0
+ return super().initial_form_count()
+
@classmethod
def get_default_prefix(cls):
opts = cls.model._meta
diff --git a/tests/generic_relations/test_forms.py b/tests/generic_relations/test_forms.py
index bed31034be..99ae882693 100644
--- a/tests/generic_relations/test_forms.py
+++ b/tests/generic_relations/test_forms.py
@@ -200,3 +200,40 @@ id="id_generic_relations-taggeditem-content_type-object_id-1-id" /></p>""" % tag
self.assertTrue(formset.is_valid())
new_obj, = formset.save()
self.assertNotIsInstance(new_obj.obj, ProxyRelatedModel)
+
+ def test_initial_count(self):
+ GenericFormSet = generic_inlineformset_factory(TaggedItem)
+ data = {
+ 'form-TOTAL_FORMS': '3',
+ 'form-INITIAL_FORMS': '3',
+ 'form-MAX_NUM_FORMS': '',
+ }
+ formset = GenericFormSet(data=data, prefix='form')
+ self.assertEqual(formset.initial_form_count(), 3)
+ formset = GenericFormSet(data=data, prefix='form', save_as_new=True)
+ self.assertEqual(formset.initial_form_count(), 0)
+
+ def test_save_as_new(self):
+ """
+ The save_as_new parameter creates new items that are associated with
+ the object.
+ """
+ lion = Animal.objects.create(common_name='Lion', latin_name='Panthera leo')
+ yellow = lion.tags.create(tag='yellow')
+ hairy = lion.tags.create(tag='hairy')
+ GenericFormSet = generic_inlineformset_factory(TaggedItem)
+ data = {
+ 'form-TOTAL_FORMS': '3',
+ 'form-INITIAL_FORMS': '2',
+ 'form-MAX_NUM_FORMS': '',
+ 'form-0-id': str(yellow.pk),
+ 'form-0-tag': 'hunts',
+ 'form-1-id': str(hairy.pk),
+ 'form-1-tag': 'roars',
+ }
+ formset = GenericFormSet(data, instance=lion, prefix='form', save_as_new=True)
+ self.assertTrue(formset.is_valid())
+ tags = formset.save()
+ self.assertEqual([tag.tag for tag in tags], ['hunts', 'roars'])
+ hunts, roars = tags
+ self.assertSequenceEqual(lion.tags.order_by('tag'), [hairy, hunts, roars, yellow])