Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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
  • Loading branch information...
commit b88f969789a5d69c770c25e1af9a2f4292184a6f 1 parent a2c4ad1
@jkocherhans jkocherhans authored
View
8 django/forms/forms.py
@@ -265,6 +265,7 @@ def full_clean(self):
return
self._clean_fields()
self._clean_form()
+ self._post_clean()
if self._errors:
delattr(self, 'cleaned_data')
@@ -295,6 +296,13 @@ def _clean_form(self):
except ValidationError, e:
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):
"""
Hook for doing any extra form-wide cleaning after Field.clean() been
View
31 django/forms/models.py
@@ -245,6 +245,10 @@ def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
# if initial was provided, it should override the values from instance
if initial is not None:
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,
error_class, label_suffix, empty_permitted)
@@ -299,34 +303,31 @@ def _get_validation_exclusions(self):
return exclude
def clean(self):
- self.validate_unique()
+ self._validate_unique = True
return self.cleaned_data
- def _clean_fields(self):
- """
- Cleans the form fields, constructs the instance, then cleans the model
- fields.
- """
- super(BaseModelForm, self)._clean_fields()
+ def _post_clean(self):
+ 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)
- exclude = self._get_validation_exclusions()
+
+ # Clean the model instance's fields.
try:
self.instance.clean_fields(exclude=exclude)
except ValidationError, e:
self._update_errors(e.message_dict)
- def _clean_form(self):
- """
- 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.
- """
+ # Call the model instance's clean method.
try:
self.instance.clean()
except ValidationError, e:
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):
"""
View
20 tests/regressiontests/model_forms_regress/tests.py
@@ -72,6 +72,26 @@ def test_override_clean(self):
# by form.full_clean().
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 Meta:
model = FilePathModel
Please sign in to comment.
Something went wrong with that request. Please try again.