Fixed #12960. The return value of ModelForm.clean() is now applied to the model. Thanks for the report, krejcik.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12690 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a2c4ad1dab
commit
b88f969789
|
@ -265,6 +265,7 @@ class BaseForm(StrAndUnicode):
|
||||||
return
|
return
|
||||||
self._clean_fields()
|
self._clean_fields()
|
||||||
self._clean_form()
|
self._clean_form()
|
||||||
|
self._post_clean()
|
||||||
if self._errors:
|
if self._errors:
|
||||||
delattr(self, 'cleaned_data')
|
delattr(self, 'cleaned_data')
|
||||||
|
|
||||||
|
@ -295,6 +296,13 @@ class BaseForm(StrAndUnicode):
|
||||||
except ValidationError, e:
|
except ValidationError, e:
|
||||||
self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
|
self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
|
||||||
|
|
||||||
|
def _post_clean(self):
|
||||||
|
"""
|
||||||
|
An internal hook for performing additional cleaning after form cleaning
|
||||||
|
is complete. Used for model validation in model forms.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
"""
|
"""
|
||||||
Hook for doing any extra form-wide cleaning after Field.clean() been
|
Hook for doing any extra form-wide cleaning after Field.clean() been
|
||||||
|
|
|
@ -245,6 +245,10 @@ class BaseModelForm(BaseForm):
|
||||||
# if initial was provided, it should override the values from instance
|
# if initial was provided, it should override the values from instance
|
||||||
if initial is not None:
|
if initial is not None:
|
||||||
object_data.update(initial)
|
object_data.update(initial)
|
||||||
|
# self._validate_unique will be set to True by BaseModelForm.clean().
|
||||||
|
# It is False by default so overriding self.clean() and failing to call
|
||||||
|
# super will stop validate_unique from being called.
|
||||||
|
self._validate_unique = False
|
||||||
super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
|
super(BaseModelForm, self).__init__(data, files, auto_id, prefix, object_data,
|
||||||
error_class, label_suffix, empty_permitted)
|
error_class, label_suffix, empty_permitted)
|
||||||
|
|
||||||
|
@ -299,34 +303,31 @@ class BaseModelForm(BaseForm):
|
||||||
return exclude
|
return exclude
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
self.validate_unique()
|
self._validate_unique = True
|
||||||
return self.cleaned_data
|
return self.cleaned_data
|
||||||
|
|
||||||
def _clean_fields(self):
|
def _post_clean(self):
|
||||||
"""
|
|
||||||
Cleans the form fields, constructs the instance, then cleans the model
|
|
||||||
fields.
|
|
||||||
"""
|
|
||||||
super(BaseModelForm, self)._clean_fields()
|
|
||||||
opts = self._meta
|
|
||||||
self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
|
|
||||||
exclude = self._get_validation_exclusions()
|
exclude = self._get_validation_exclusions()
|
||||||
|
opts = self._meta
|
||||||
|
|
||||||
|
# Update the model instance with self.cleaned_data.
|
||||||
|
self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
|
||||||
|
|
||||||
|
# Clean the model instance's fields.
|
||||||
try:
|
try:
|
||||||
self.instance.clean_fields(exclude=exclude)
|
self.instance.clean_fields(exclude=exclude)
|
||||||
except ValidationError, e:
|
except ValidationError, e:
|
||||||
self._update_errors(e.message_dict)
|
self._update_errors(e.message_dict)
|
||||||
|
|
||||||
def _clean_form(self):
|
# Call the model instance's clean method.
|
||||||
"""
|
|
||||||
Runs the instance's clean method, then the form's. This is becuase the
|
|
||||||
form will run validate_unique() by default, and we should run the
|
|
||||||
model's clean method first.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
self.instance.clean()
|
self.instance.clean()
|
||||||
except ValidationError, e:
|
except ValidationError, e:
|
||||||
self._update_errors({NON_FIELD_ERRORS: e.messages})
|
self._update_errors({NON_FIELD_ERRORS: e.messages})
|
||||||
super(BaseModelForm, self)._clean_form()
|
|
||||||
|
# Validate uniqueness if needed.
|
||||||
|
if self._validate_unique:
|
||||||
|
self.validate_unique()
|
||||||
|
|
||||||
def validate_unique(self):
|
def validate_unique(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -72,6 +72,26 @@ class OverrideCleanTests(TestCase):
|
||||||
# by form.full_clean().
|
# by form.full_clean().
|
||||||
self.assertEquals(form.instance.left, 1)
|
self.assertEquals(form.instance.left, 1)
|
||||||
|
|
||||||
|
# Regression test for #12960.
|
||||||
|
# Make sure the cleaned_data returned from ModelForm.clean() is applied to the
|
||||||
|
# model instance.
|
||||||
|
|
||||||
|
class PublicationForm(forms.ModelForm):
|
||||||
|
def clean(self):
|
||||||
|
print self.cleaned_data
|
||||||
|
self.cleaned_data['title'] = self.cleaned_data['title'].upper()
|
||||||
|
return self.cleaned_data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Publication
|
||||||
|
|
||||||
|
class ModelFormCleanTest(TestCase):
|
||||||
|
def test_model_form_clean_applies_to_model(self):
|
||||||
|
data = {'title': 'test', 'date_published': '2010-2-25'}
|
||||||
|
form = PublicationForm(data)
|
||||||
|
publication = form.save()
|
||||||
|
self.assertEqual(publication.title, 'TEST')
|
||||||
|
|
||||||
class FPForm(forms.ModelForm):
|
class FPForm(forms.ModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = FilePathModel
|
model = FilePathModel
|
||||||
|
|
Loading…
Reference in New Issue