Fixed #28159 -- Fixed BaseInlineFormSet._construct_form() crash when using save_as_new.
Regression in 4a246a02bd
.
This commit is contained in:
parent
9b2d47bcde
commit
362fba87c9
|
@ -884,12 +884,17 @@ class BaseInlineFormSet(BaseModelFormSet):
|
||||||
def _construct_form(self, i, **kwargs):
|
def _construct_form(self, i, **kwargs):
|
||||||
form = super()._construct_form(i, **kwargs)
|
form = super()._construct_form(i, **kwargs)
|
||||||
if self.save_as_new:
|
if self.save_as_new:
|
||||||
|
mutable = getattr(form.data, '_mutable', None)
|
||||||
|
# Allow modifying an immutable QueryDict.
|
||||||
|
if mutable is not None:
|
||||||
|
form.data._mutable = True
|
||||||
# Remove the primary key from the form's data, we are only
|
# Remove the primary key from the form's data, we are only
|
||||||
# creating new instances
|
# creating new instances
|
||||||
form.data[form.add_prefix(self._pk_field.name)] = None
|
form.data[form.add_prefix(self._pk_field.name)] = None
|
||||||
|
|
||||||
# Remove the foreign key from the form's data
|
# Remove the foreign key from the form's data
|
||||||
form.data[form.add_prefix(self.fk.name)] = None
|
form.data[form.add_prefix(self.fk.name)] = None
|
||||||
|
if mutable is not None:
|
||||||
|
form.data._mutable = mutable
|
||||||
|
|
||||||
# Set the fk value here so that the form can do its validation.
|
# Set the fk value here so that the form can do its validation.
|
||||||
fk_value = self.instance.pk
|
fk_value = self.instance.pk
|
||||||
|
|
|
@ -81,3 +81,6 @@ Bugfixes
|
||||||
|
|
||||||
* Fixed a regression in choice ordering in form fields with grouped and
|
* Fixed a regression in choice ordering in form fields with grouped and
|
||||||
non-grouped options (:ticket:`28157`).
|
non-grouped options (:ticket:`28157`).
|
||||||
|
|
||||||
|
* Fixed crash in ``BaseInlineFormSet._construct_form()`` when using
|
||||||
|
``save_as_new`` (:ticket:`28159`).
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.forms.models import (
|
||||||
BaseModelFormSet, _get_foreign_key, inlineformset_factory,
|
BaseModelFormSet, _get_foreign_key, inlineformset_factory,
|
||||||
modelformset_factory,
|
modelformset_factory,
|
||||||
)
|
)
|
||||||
|
from django.http import QueryDict
|
||||||
from django.test import TestCase, skipUnlessDBFeature
|
from django.test import TestCase, skipUnlessDBFeature
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
|
@ -699,7 +700,9 @@ class ModelFormsetTest(TestCase):
|
||||||
AuthorBooksFormSet = inlineformset_factory(Author, Book, can_delete=False, extra=2, fields="__all__")
|
AuthorBooksFormSet = inlineformset_factory(Author, Book, can_delete=False, extra=2, fields="__all__")
|
||||||
Author.objects.create(name='Charles Baudelaire')
|
Author.objects.create(name='Charles Baudelaire')
|
||||||
|
|
||||||
data = {
|
# An immutable QueryDict simulates request.POST.
|
||||||
|
data = QueryDict(mutable=True)
|
||||||
|
data.update({
|
||||||
'book_set-TOTAL_FORMS': '3', # the number of forms rendered
|
'book_set-TOTAL_FORMS': '3', # the number of forms rendered
|
||||||
'book_set-INITIAL_FORMS': '2', # the number of forms with initial data
|
'book_set-INITIAL_FORMS': '2', # the number of forms with initial data
|
||||||
'book_set-MAX_NUM_FORMS': '', # the max number of forms
|
'book_set-MAX_NUM_FORMS': '', # the max number of forms
|
||||||
|
@ -708,10 +711,12 @@ class ModelFormsetTest(TestCase):
|
||||||
'book_set-1-id': '2',
|
'book_set-1-id': '2',
|
||||||
'book_set-1-title': 'Les Paradis Artificiels',
|
'book_set-1-title': 'Les Paradis Artificiels',
|
||||||
'book_set-2-title': '',
|
'book_set-2-title': '',
|
||||||
}
|
})
|
||||||
|
data._mutable = False
|
||||||
|
|
||||||
formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True)
|
formset = AuthorBooksFormSet(data, instance=Author(), save_as_new=True)
|
||||||
self.assertTrue(formset.is_valid())
|
self.assertTrue(formset.is_valid())
|
||||||
|
self.assertIs(data._mutable, False)
|
||||||
|
|
||||||
new_author = Author.objects.create(name='Charles Baudelaire')
|
new_author = Author.objects.create(name='Charles Baudelaire')
|
||||||
formset = AuthorBooksFormSet(data, instance=new_author, save_as_new=True)
|
formset = AuthorBooksFormSet(data, instance=new_author, save_as_new=True)
|
||||||
|
|
Loading…
Reference in New Issue