mirror of
https://github.com/django/django.git
synced 2024-12-31 21:46:05 +00:00
Fixed #27416 -- Prevented ModelFormSet from creating objects for invalid PKs in data.
This commit is contained in:
parent
373140b07a
commit
181f492ad0
@ -755,12 +755,13 @@ class BaseModelFormSet(BaseFormSet):
|
|||||||
forms_to_delete = self.deleted_forms
|
forms_to_delete = self.deleted_forms
|
||||||
for form in self.initial_forms:
|
for form in self.initial_forms:
|
||||||
obj = form.instance
|
obj = form.instance
|
||||||
|
# If the pk is None, it means either:
|
||||||
|
# 1. The object is an unexpected empty model, created by invalid
|
||||||
|
# POST data such as an object outside the formset's queryset.
|
||||||
|
# 2. The object was already deleted from the database.
|
||||||
|
if obj.pk is None:
|
||||||
|
continue
|
||||||
if form in forms_to_delete:
|
if form in forms_to_delete:
|
||||||
# If the pk is None, it means that the object can't be
|
|
||||||
# deleted again. Possible reason for this is that the
|
|
||||||
# object was already deleted from the DB. Refs #14877.
|
|
||||||
if obj.pk is None:
|
|
||||||
continue
|
|
||||||
self.deleted_objects.append(obj)
|
self.deleted_objects.append(obj)
|
||||||
self.delete_existing(obj, commit=commit)
|
self.delete_existing(obj, commit=commit)
|
||||||
elif form.has_changed():
|
elif form.has_changed():
|
||||||
|
@ -1631,6 +1631,28 @@ class ModelFormsetTest(TestCase):
|
|||||||
['Please correct the duplicate data for subtitle which must be unique for the month in posted.']
|
['Please correct the duplicate data for subtitle which must be unique for the month in posted.']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_prevent_change_outer_model_and_create_invalid_data(self):
|
||||||
|
author = Author.objects.create(name='Charles')
|
||||||
|
other_author = Author.objects.create(name='Walt')
|
||||||
|
AuthorFormSet = modelformset_factory(Author, fields='__all__')
|
||||||
|
data = {
|
||||||
|
'form-TOTAL_FORMS': '2',
|
||||||
|
'form-INITIAL_FORMS': '2',
|
||||||
|
'form-MAX_NUM_FORMS': '',
|
||||||
|
'form-0-id': str(author.id),
|
||||||
|
'form-0-name': 'Charles',
|
||||||
|
'form-1-id': str(other_author.id), # A model not in the formset's queryset.
|
||||||
|
'form-1-name': 'Changed name',
|
||||||
|
}
|
||||||
|
# This formset is only for Walt Whitman and shouldn't accept data for
|
||||||
|
# other_author.
|
||||||
|
formset = AuthorFormSet(data=data, queryset=Author.objects.filter(id__in=(author.id,)))
|
||||||
|
self.assertTrue(formset.is_valid())
|
||||||
|
formset.save()
|
||||||
|
# The name of other_author shouldn't be changed and new models aren't
|
||||||
|
# created.
|
||||||
|
self.assertQuerysetEqual(Author.objects.all(), ['<Author: Charles>', '<Author: Walt>'])
|
||||||
|
|
||||||
|
|
||||||
class TestModelFormsetOverridesTroughFormMeta(TestCase):
|
class TestModelFormsetOverridesTroughFormMeta(TestCase):
|
||||||
def test_modelformset_factory_widgets(self):
|
def test_modelformset_factory_widgets(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user