Fixed #4960 -- Added "strip" option to CharField

This commit is contained in:
Curtis 2015-02-05 23:26:15 +11:00 committed by Tim Graham
parent b535eb3fcb
commit 11cac1bd8e
4 changed files with 48 additions and 11 deletions

View File

@ -210,8 +210,10 @@ class Field(six.with_metaclass(RenameFieldMethods, object)):
class CharField(Field):
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
self.max_length, self.min_length = max_length, min_length
def __init__(self, max_length=None, min_length=None, strip=True, *args, **kwargs):
self.max_length = max_length
self.min_length = min_length
self.strip = strip
super(CharField, self).__init__(*args, **kwargs)
if min_length is not None:
self.validators.append(validators.MinLengthValidator(int(min_length)))
@ -222,7 +224,10 @@ class CharField(Field):
"Returns a Unicode object."
if value in self.empty_values:
return ''
return smart_text(value)
value = force_text(value)
if self.strip:
value = value.strip()
return value
def widget_attrs(self, widget):
attrs = super(CharField, self).widget_attrs(widget)
@ -539,6 +544,7 @@ class RegexField(CharField):
error_message is an optional error message to use, if
'Enter a valid value' is too generic for you.
"""
kwargs.setdefault('strip', False)
# error_message is just kept for backwards compatibility:
if error_message is not None:
warnings.warn(
@ -1231,10 +1237,6 @@ class GenericIPAddressField(CharField):
class SlugField(CharField):
default_validators = [validators.validate_slug]
def clean(self, value):
value = self.to_python(value).strip()
return super(SlugField, self).clean(value)
class UUIDField(CharField):
default_error_messages = {

View File

@ -361,7 +361,7 @@ For each field, we describe the default widget used if you don't specify
Otherwise, all inputs are valid.
* Error message keys: ``required``, ``max_length``, ``min_length``
Has two optional arguments for validation:
Has three optional arguments for validation:
.. attribute:: max_length
.. attribute:: min_length
@ -369,6 +369,13 @@ For each field, we describe the default widget used if you don't specify
If provided, these arguments ensure that the string is at most or at least
the given length.
.. attribute:: strip
.. versionadded:: 1.9
If ``True`` (default), the value will be stripped of leading and
trailing whitespace.
``ChoiceField``
~~~~~~~~~~~~~~~
@ -824,8 +831,15 @@ For each field, we describe the default widget used if you don't specify
A regular expression specified either as a string or a compiled regular
expression object.
Also takes ``max_length`` and ``min_length``, which work just as they do for
``CharField``.
Also takes ``max_length``, ``min_length``, and ``strip``, which work just
as they do for ``CharField``.
.. attribute:: strip
.. versionadded:: 1.9
Defaults to ``False``. If enabled, stripping will be applied before the
regex validation.
.. deprecated:: 1.8

View File

@ -302,6 +302,11 @@ Forms
* You can now :ref:`specify keyword arguments <custom-formset-form-kwargs>`
that you want to pass to the constructor of forms in a formset.
* :class:`~django.forms.CharField` now accepts a
:attr:`~django.forms.CharField.strip` argument to strip input data of leading
and trailing whitespace. As this defaults to ``True`` this is different
behavior from previous releases.
Generic Views
^^^^^^^^^^^^^
@ -822,6 +827,10 @@ Miscellaneous
be serialized contains any control characters not allowed in the XML 1.0
standard, the serialization will fail with a :exc:`ValueError`.
* :class:`~django.forms.CharField` now strips input of leading and trailing
whitespace by default. This can be disabled by setting the new
:attr:`~django.forms.CharField.strip` argument to ``False``.
.. _deprecated-features-1.9:
Features deprecated in 1.9

View File

@ -164,6 +164,18 @@ class FieldsTests(SimpleTestCase):
self.assertEqual(f.widget_attrs(PasswordInput()), {'maxlength': '10'})
self.assertEqual(f.widget_attrs(Textarea()), {'maxlength': '10'})
def test_charfield_strip(self):
"""
Ensure that values have whitespace stripped and that strip=False works.
"""
f = CharField()
self.assertEqual(f.clean(' 1'), '1')
self.assertEqual(f.clean('1 '), '1')
f = CharField(strip=False)
self.assertEqual(f.clean(' 1'), ' 1')
self.assertEqual(f.clean('1 '), '1 ')
# IntegerField ################################################################
def test_integerfield_1(self):