[4.1.x] Fixed #33822 -- Fixed save() crash on model formsets when not created by modelformset_factory().

Thanks Claude Paroz for the report.

Regression in e87f57fdb8.

Backport of 18c5ba07cc from main
This commit is contained in:
Shawn Dong 2022-07-04 10:45:28 -07:00 committed by Mariusz Felisiak
parent ee79219f1b
commit 675d2239ce
2 changed files with 32 additions and 0 deletions

View File

@ -657,6 +657,7 @@ class BaseModelFormSet(BaseFormSet):
""" """
model = None model = None
edit_only = False
# Set of fields that must be unique among forms of this set. # Set of fields that must be unique among forms of this set.
unique_fields = set() unique_fields = set()

View File

@ -6,6 +6,7 @@ from decimal import Decimal
from django import forms from django import forms
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.db import models from django.db import models
from django.forms.formsets import formset_factory
from django.forms.models import ( from django.forms.models import (
BaseModelFormSet, BaseModelFormSet,
_get_foreign_key, _get_foreign_key,
@ -2066,6 +2067,36 @@ class ModelFormsetTest(TestCase):
formset.save() formset.save()
self.assertCountEqual(Author.objects.all(), [charles, walt]) self.assertCountEqual(Author.objects.all(), [charles, walt])
def test_edit_only_formset_factory_with_basemodelformset(self):
charles = Author.objects.create(name="Charles Baudelaire")
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = "__all__"
class BaseAuthorFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
self.model = Author
super().__init__(*args, **kwargs)
AuthorFormSet = formset_factory(AuthorForm, formset=BaseAuthorFormSet)
data = {
"form-TOTAL_FORMS": "2",
"form-INITIAL_FORMS": "1",
"form-MAX_NUM_FORMS": "0",
"form-0-id": charles.pk,
"form-0-name": "Shawn Dong",
"form-1-name": "Walt Whitman",
}
formset = AuthorFormSet(data)
self.assertIs(formset.is_valid(), True)
formset.save()
self.assertEqual(Author.objects.count(), 2)
charles.refresh_from_db()
self.assertEqual(charles.name, "Shawn Dong")
self.assertEqual(Author.objects.count(), 2)
class TestModelFormsetOverridesTroughFormMeta(TestCase): class TestModelFormsetOverridesTroughFormMeta(TestCase):
def test_modelformset_factory_widgets(self): def test_modelformset_factory_widgets(self):