Loading django/forms/models.py +4 −0 Original line number Diff line number Diff line Loading @@ -904,6 +904,10 @@ class BaseInlineFormSet(BaseModelFormSet): return cls.fk.rel.get_accessor_name(model=cls.model).replace('+', '') def save_new(self, form, commit=True): # Ensure the latest copy of the related instance is present on each # form (it may have been saved after the formset was originally # instantiated). setattr(form.instance, self.fk.name, self.instance) # Use commit=False so we can assign the parent key afterwards, then # save the object. obj = form.save(commit=False) Loading tests/model_formsets/tests.py +32 −0 Original line number Diff line number Diff line Loading @@ -819,6 +819,38 @@ class ModelFormsetTest(TestCase): formset = AuthorBooksFormSet(data, instance=author, queryset=custom_qs) self.assertTrue(formset.is_valid()) def test_inline_formsets_with_custom_save_method_related_instance(self): """ The ModelForm.save() method should be able to access the related object if it exists in the database (#24395). """ class PoemForm2(forms.ModelForm): def save(self, commit=True): poem = super(PoemForm2, self).save(commit=False) poem.name = "%s by %s" % (poem.name, poem.poet.name) if commit: poem.save() return poem PoemFormSet = inlineformset_factory(Poet, Poem, form=PoemForm2, fields="__all__") data = { 'poem_set-TOTAL_FORMS': '1', 'poem_set-INITIAL_FORMS': '0', 'poem_set-MAX_NUM_FORMS': '', 'poem_set-0-name': 'Le Lac', } poet = Poet() formset = PoemFormSet(data=data, instance=poet) self.assertTrue(formset.is_valid()) # The Poet instance is saved after the formset instantiation. This # happens in admin's changeform_view() when adding a new object and # some inlines in the same request. poet.name = 'Lamartine' poet.save() poem = formset.save()[0] self.assertEqual(poem.name, 'Le Lac by Lamartine') def test_inline_formsets_with_wrong_fk_name(self): """ Regression for #23451 """ message = "fk_name 'title' is not a ForeignKey to 'model_formsets.Author'." Loading Loading
django/forms/models.py +4 −0 Original line number Diff line number Diff line Loading @@ -904,6 +904,10 @@ class BaseInlineFormSet(BaseModelFormSet): return cls.fk.rel.get_accessor_name(model=cls.model).replace('+', '') def save_new(self, form, commit=True): # Ensure the latest copy of the related instance is present on each # form (it may have been saved after the formset was originally # instantiated). setattr(form.instance, self.fk.name, self.instance) # Use commit=False so we can assign the parent key afterwards, then # save the object. obj = form.save(commit=False) Loading
tests/model_formsets/tests.py +32 −0 Original line number Diff line number Diff line Loading @@ -819,6 +819,38 @@ class ModelFormsetTest(TestCase): formset = AuthorBooksFormSet(data, instance=author, queryset=custom_qs) self.assertTrue(formset.is_valid()) def test_inline_formsets_with_custom_save_method_related_instance(self): """ The ModelForm.save() method should be able to access the related object if it exists in the database (#24395). """ class PoemForm2(forms.ModelForm): def save(self, commit=True): poem = super(PoemForm2, self).save(commit=False) poem.name = "%s by %s" % (poem.name, poem.poet.name) if commit: poem.save() return poem PoemFormSet = inlineformset_factory(Poet, Poem, form=PoemForm2, fields="__all__") data = { 'poem_set-TOTAL_FORMS': '1', 'poem_set-INITIAL_FORMS': '0', 'poem_set-MAX_NUM_FORMS': '', 'poem_set-0-name': 'Le Lac', } poet = Poet() formset = PoemFormSet(data=data, instance=poet) self.assertTrue(formset.is_valid()) # The Poet instance is saved after the formset instantiation. This # happens in admin's changeform_view() when adding a new object and # some inlines in the same request. poet.name = 'Lamartine' poet.save() poem = formset.save()[0] self.assertEqual(poem.name, 'Le Lac by Lamartine') def test_inline_formsets_with_wrong_fk_name(self): """ Regression for #23451 """ message = "fk_name 'title' is not a ForeignKey to 'model_formsets.Author'." Loading