diff --git a/django/forms/fields.py b/django/forms/fields.py index 40fdb24a10..805018786a 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -221,11 +221,12 @@ class CharField(Field): def to_python(self, value): """Return a string.""" + if value not in self.empty_values: + value = str(value) + if self.strip: + value = value.strip() if value in self.empty_values: return self.empty_value - value = str(value) - if self.strip: - value = value.strip() return value def widget_attrs(self, widget): diff --git a/tests/forms_tests/field_tests/test_charfield.py b/tests/forms_tests/field_tests/test_charfield.py index 8f6a27f473..ad91070571 100644 --- a/tests/forms_tests/field_tests/test_charfield.py +++ b/tests/forms_tests/field_tests/test_charfield.py @@ -120,6 +120,29 @@ class CharFieldTest(FormFieldAssertionsMixin, SimpleTestCase): self.assertEqual(f.clean(' 1'), ' 1') self.assertEqual(f.clean('1 '), '1 ') + def test_strip_before_checking_empty(self): + """ + A whitespace-only value, ' ', is stripped to an empty string and then + converted to the empty value, None. + """ + f = CharField(required=False, empty_value=None) + self.assertIsNone(f.clean(' ')) + + def test_clean_non_string(self): + """CharField.clean() calls str(value) before stripping it.""" + class StringWrapper: + def __init__(self, v): + self.v = v + + def __str__(self): + return self.v + + value = StringWrapper(' ') + f1 = CharField(required=False, empty_value=None) + self.assertIsNone(f1.clean(value)) + f2 = CharField(strip=False) + self.assertEqual(f2.clean(value), ' ') + def test_charfield_disabled(self): f = CharField(disabled=True) self.assertWidgetRendersTo(f, '')