Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Form.clean() does not need to return cleaned_data.

If it does, that will be used as the cleaned_data. The default
implementation has been changed to match this change.
  • Loading branch information...
commit fb1dd6b13a0e6b1ef64eac88467321d097942cd2 1 parent 7a2296e
Marc Tamlyn authored August 08, 2013
7  django/forms/forms.py
@@ -297,9 +297,12 @@ def _clean_fields(self):
297 297
 
298 298
     def _clean_form(self):
299 299
         try:
300  
-            self.cleaned_data = self.clean()
  300
+            cleaned_data = self.clean()
301 301
         except ValidationError as e:
302 302
             self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
  303
+        else:
  304
+            if cleaned_data is not None:
  305
+                self.cleaned_data = cleaned_data
303 306
 
304 307
     def _post_clean(self):
305 308
         """
@@ -315,7 +318,7 @@ def clean(self):
315 318
         not be associated with a particular field; it will have a special-case
316 319
         association with the field named '__all__'.
317 320
         """
318  
-        return self.cleaned_data
  321
+        pass
319 322
 
320 323
     def has_changed(self):
321 324
         """
12  docs/ref/forms/validation.txt
@@ -75,10 +75,8 @@ overridden:
75 75
   any validation that requires access to multiple fields from the form at
76 76
   once. This is where you might put in things to check that if field ``A``
77 77
   is supplied, field ``B`` must contain a valid email address and the
78  
-  like. The data that this method returns is the final ``cleaned_data``
79  
-  attribute for the form, so don't forget to return the full list of
80  
-  cleaned data if you override this method (by default, ``Form.clean()``
81  
-  just returns ``self.cleaned_data``).
  78
+  like. This method can return a completely different dictionary if it wishes,
  79
+  which will be used as the ``cleaned_data``.
82 80
 
83 81
   Note that any errors raised by your ``Form.clean()`` override will not
84 82
   be associated with any field in particular. They go into a special
@@ -403,9 +401,6 @@ example::
403 401
                     raise forms.ValidationError("Did not send for 'help' in "
404 402
                             "the subject despite CC'ing yourself.")
405 403
 
406  
-            # Always return the full collection of cleaned data.
407  
-            return cleaned_data
408  
-
409 404
 In this code, if the validation error is raised, the form will display an
410 405
 error message at the top of the form (normally) describing the problem.
411 406
 
@@ -443,9 +438,6 @@ sample) looks like this::
443 438
                 del cleaned_data["cc_myself"]
444 439
                 del cleaned_data["subject"]
445 440
 
446  
-            # Always return the full collection of cleaned data.
447  
-            return cleaned_data
448  
-
449 441
 As you can see, this approach requires a bit more effort, not withstanding the
450 442
 extra design effort to create a sensible form display. The details are worth
451 443
 noting, however. Firstly, earlier we mentioned that you might need to check if
5  docs/releases/1.7.txt
@@ -127,6 +127,11 @@ Minor features
127 127
   for each individual field will be respected, and a new ``incomplete``
128 128
   validation error will be raised when any required fields are empty.
129 129
 
  130
+* The :meth:`~django.forms.Form.clean` method on a form no longer needs to
  131
+  return ``self.cleaned_data``. If it does return a changed dictionary then
  132
+  that will still be used. The default implementation no longer returns
  133
+  ``self.cleaned_data``.
  134
+
130 135
 Backwards incompatible changes in 1.7
131 136
 =====================================
132 137
 
18  tests/forms_tests/tests/test_extra.py
@@ -620,6 +620,24 @@ def clean(self):
620 620
         self.assertTrue(f.is_valid())
621 621
         self.assertEqual(f.cleaned_data['username'], 'sirrobin')
622 622
 
  623
+    def test_changing_cleaned_data_in_clean(self):
  624
+        class UserForm(Form):
  625
+            username = CharField(max_length=10)
  626
+            password = CharField(widget=PasswordInput)
  627
+
  628
+            def clean(self):
  629
+                data = self.cleaned_data
  630
+
  631
+                # Return a different dict. We have not changed self.cleaned_data.
  632
+                return {
  633
+                    'username': data['username'].lower(),
  634
+                    'password': 'this_is_not_a_secret',
  635
+                }
  636
+
  637
+        f = UserForm({'username': 'SirRobin', 'password': 'blue'})
  638
+        self.assertTrue(f.is_valid())
  639
+        self.assertEqual(f.cleaned_data['username'], 'sirrobin')
  640
+
623 641
     def test_overriding_errorlist(self):
624 642
         @python_2_unicode_compatible
625 643
         class DivErrorList(ErrorList):

0 notes on commit fb1dd6b

Please sign in to comment.
Something went wrong with that request. Please try again.