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.
This commit is contained in:
Marc Tamlyn 2013-08-08 14:05:55 +01:00
parent 7a2296eb5b
commit fb1dd6b13a
4 changed files with 30 additions and 12 deletions

View File

@ -297,9 +297,12 @@ class BaseForm(object):
def _clean_form(self): def _clean_form(self):
try: try:
self.cleaned_data = self.clean() cleaned_data = self.clean()
except ValidationError as e: except ValidationError as e:
self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages) self._errors[NON_FIELD_ERRORS] = self.error_class(e.messages)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data
def _post_clean(self): def _post_clean(self):
""" """
@ -315,7 +318,7 @@ class BaseForm(object):
not be associated with a particular field; it will have a special-case not be associated with a particular field; it will have a special-case
association with the field named '__all__'. association with the field named '__all__'.
""" """
return self.cleaned_data pass
def has_changed(self): def has_changed(self):
""" """

View File

@ -75,10 +75,8 @@ overridden:
any validation that requires access to multiple fields from the form at any validation that requires access to multiple fields from the form at
once. This is where you might put in things to check that if field ``A`` once. This is where you might put in things to check that if field ``A``
is supplied, field ``B`` must contain a valid email address and the is supplied, field ``B`` must contain a valid email address and the
like. The data that this method returns is the final ``cleaned_data`` like. This method can return a completely different dictionary if it wishes,
attribute for the form, so don't forget to return the full list of which will be used as the ``cleaned_data``.
cleaned data if you override this method (by default, ``Form.clean()``
just returns ``self.cleaned_data``).
Note that any errors raised by your ``Form.clean()`` override will not Note that any errors raised by your ``Form.clean()`` override will not
be associated with any field in particular. They go into a special be associated with any field in particular. They go into a special
@ -403,9 +401,6 @@ example::
raise forms.ValidationError("Did not send for 'help' in " raise forms.ValidationError("Did not send for 'help' in "
"the subject despite CC'ing yourself.") "the subject despite CC'ing yourself.")
# Always return the full collection of cleaned data.
return cleaned_data
In this code, if the validation error is raised, the form will display an In this code, if the validation error is raised, the form will display an
error message at the top of the form (normally) describing the problem. error message at the top of the form (normally) describing the problem.
@ -443,9 +438,6 @@ sample) looks like this::
del cleaned_data["cc_myself"] del cleaned_data["cc_myself"]
del cleaned_data["subject"] del cleaned_data["subject"]
# Always return the full collection of cleaned data.
return cleaned_data
As you can see, this approach requires a bit more effort, not withstanding the As you can see, this approach requires a bit more effort, not withstanding the
extra design effort to create a sensible form display. The details are worth extra design effort to create a sensible form display. The details are worth
noting, however. Firstly, earlier we mentioned that you might need to check if noting, however. Firstly, earlier we mentioned that you might need to check if

View File

@ -127,6 +127,11 @@ Minor features
for each individual field will be respected, and a new ``incomplete`` for each individual field will be respected, and a new ``incomplete``
validation error will be raised when any required fields are empty. validation error will be raised when any required fields are empty.
* The :meth:`~django.forms.Form.clean` method on a form no longer needs to
return ``self.cleaned_data``. If it does return a changed dictionary then
that will still be used. The default implementation no longer returns
``self.cleaned_data``.
Backwards incompatible changes in 1.7 Backwards incompatible changes in 1.7
===================================== =====================================

View File

@ -620,6 +620,24 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
self.assertTrue(f.is_valid()) self.assertTrue(f.is_valid())
self.assertEqual(f.cleaned_data['username'], 'sirrobin') self.assertEqual(f.cleaned_data['username'], 'sirrobin')
def test_changing_cleaned_data_in_clean(self):
class UserForm(Form):
username = CharField(max_length=10)
password = CharField(widget=PasswordInput)
def clean(self):
data = self.cleaned_data
# Return a different dict. We have not changed self.cleaned_data.
return {
'username': data['username'].lower(),
'password': 'this_is_not_a_secret',
}
f = UserForm({'username': 'SirRobin', 'password': 'blue'})
self.assertTrue(f.is_valid())
self.assertEqual(f.cleaned_data['username'], 'sirrobin')
def test_overriding_errorlist(self): def test_overriding_errorlist(self):
@python_2_unicode_compatible @python_2_unicode_compatible
class DivErrorList(ErrorList): class DivErrorList(ErrorList):