Fixed #12337 - Honor ModelForm.Meta.exclude when saving ManyToManyFields.
Thanks margieroginski for the report.
This commit is contained in:
parent
b67f2ac8e6
commit
e2518fdf46
|
@ -85,6 +85,8 @@ def save_instance(form, instance, fields=None, fail_message='saved',
|
|||
for f in opts.many_to_many:
|
||||
if fields and f.name not in fields:
|
||||
continue
|
||||
if exclude and f.name in exclude:
|
||||
continue
|
||||
if f.name in cleaned_data:
|
||||
f.save_form_data(instance, cleaned_data[f.name])
|
||||
if commit:
|
||||
|
@ -405,7 +407,8 @@ class BaseModelForm(BaseForm):
|
|||
else:
|
||||
fail_message = 'changed'
|
||||
return save_instance(self, self.instance, self._meta.fields,
|
||||
fail_message, commit, construct=False)
|
||||
fail_message, commit, self._meta.exclude,
|
||||
construct=False)
|
||||
|
||||
save.alters_data = True
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import datetime
|
|||
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.db import models
|
||||
from django.forms import Form, ModelForm, FileField, ModelChoiceField
|
||||
from django.forms import Form, ModelForm, FileField, ModelChoiceField, CharField
|
||||
from django.forms.models import ModelFormMetaclass
|
||||
from django.test import TestCase
|
||||
from django.utils import six
|
||||
|
@ -26,6 +26,14 @@ class OptionalMultiChoiceModelForm(ModelForm):
|
|||
fields = '__all__'
|
||||
|
||||
|
||||
class ChoiceFieldExclusionForm(ModelForm):
|
||||
multi_choice = CharField(max_length=50)
|
||||
|
||||
class Meta:
|
||||
exclude = ['multi_choice']
|
||||
model = ChoiceFieldModel
|
||||
|
||||
|
||||
class FileForm(Form):
|
||||
file1 = FileField()
|
||||
|
||||
|
@ -221,3 +229,31 @@ class RelatedModelFormTests(TestCase):
|
|||
model=A
|
||||
|
||||
self.assertTrue(issubclass(ModelFormMetaclass(str('Form'), (ModelForm,), {'Meta': Meta}), ModelForm))
|
||||
|
||||
|
||||
class ManyToManyExclusionTestCase(TestCase):
|
||||
def test_m2m_field_exclusion(self):
|
||||
# Issue 12337. save_instance should honor the passed-in exclude keyword.
|
||||
opt1 = ChoiceOptionModel.objects.create(id=1, name='default')
|
||||
opt2 = ChoiceOptionModel.objects.create(id=2, name='option 2')
|
||||
opt3 = ChoiceOptionModel.objects.create(id=3, name='option 3')
|
||||
initial = {
|
||||
'choice': opt1,
|
||||
'choice_int': opt1,
|
||||
}
|
||||
data = {
|
||||
'choice': opt2.pk,
|
||||
'choice_int': opt2.pk,
|
||||
'multi_choice': 'string data!',
|
||||
'multi_choice_int': [opt1.pk],
|
||||
}
|
||||
instance = ChoiceFieldModel.objects.create(**initial)
|
||||
instance.multi_choice = instance.multi_choice_int = [opt2, opt3]
|
||||
form = ChoiceFieldExclusionForm(data=data, instance=instance)
|
||||
self.assertTrue(form.is_valid())
|
||||
self.assertEqual(form.cleaned_data['multi_choice'], data['multi_choice'])
|
||||
form.save()
|
||||
self.assertEqual(form.instance.choice.pk, data['choice'])
|
||||
self.assertEqual(form.instance.choice_int.pk, data['choice_int'])
|
||||
self.assertEqual(list(form.instance.multi_choice.all()), [opt2, opt3])
|
||||
self.assertEqual([obj.pk for obj in form.instance.multi_choice_int.all()], data['multi_choice_int'])
|
||||
|
|
Loading…
Reference in New Issue