Author: jkocherhans
Date: 2010-03-06 12:42:56 -0600 (Sat, 06 Mar 2010)
New Revision: 12690

Modified:
   django/trunk/django/forms/forms.py
   django/trunk/django/forms/models.py
   django/trunk/tests/regressiontests/model_forms_regress/tests.py
Log:
Fixed #12960. The return value of ModelForm.clean() is now applied to the 
model. Thanks for the report, krejcik.

Modified: django/trunk/django/forms/forms.py
===================================================================
--- django/trunk/django/forms/forms.py  2010-03-06 16:07:05 UTC (rev 12689)
+++ django/trunk/django/forms/forms.py  2010-03-06 18:42:56 UTC (rev 12690)
@@ -265,6 +265,7 @@
             return
         self._clean_fields()
         self._clean_form()
+        self._post_clean()
         if self._errors:
             delattr(self, 'cleaned_data')
 
@@ -295,6 +296,13 @@
         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

Modified: django/trunk/django/forms/models.py
===================================================================
--- django/trunk/django/forms/models.py 2010-03-06 16:07:05 UTC (rev 12689)
+++ django/trunk/django/forms/models.py 2010-03-06 18:42:56 UTC (rev 12690)
@@ -245,6 +245,10 @@
         # 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,35 +303,32 @@
         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):
         """
         Calls the instance's validate_unique() method and updates the form's

Modified: django/trunk/tests/regressiontests/model_forms_regress/tests.py
===================================================================
--- django/trunk/tests/regressiontests/model_forms_regress/tests.py     
2010-03-06 16:07:05 UTC (rev 12689)
+++ django/trunk/tests/regressiontests/model_forms_regress/tests.py     
2010-03-06 18:42:56 UTC (rev 12690)
@@ -72,6 +72,26 @@
         # 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

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to