Trim Spaces in Django Forms

Not sure if I agree with this ticket, but it appears Django won’t be adding support for removing leading / trailing whitespace from form fields. Other frameworks make this super easy. Hopefully the Django folks will put something together for 1.6+.

For now the best approach appears to be creating a base form class which all other forms subclass. The class looks like the following (thanks to Dave Dash and his library):

from django.forms import Form
from django.forms import ValidationError
from django.forms import FileField
# Django 1.6 Version
class BaseForm(Form):
def _clean_fields(self):
for name, field in self.fields.items():
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.files,
self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
if isinstance(value, basestring):
value = field.clean(value.strip())
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError, e:
self._errors[name] = self.error_class(e.messages)
if name in self.cleaned_data:
del self.cleaned_data[name]
# Django 1.7 Version
# (makes use of new add_error API – https://docs.djangoproject.com/en/1.7/ref/forms/api/#django.forms.Form.add_error)
class BaseForm(Form):
# strip leading or trailing whitespace
def _clean_fields(self):
for name, field in self.fields.items():
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
if isinstance(value, basestring):
value = field.clean(value.strip())
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)

view raw
forms.py
hosted with ❤ by GitHub

I have seen other posts recommending doing the work in the clean method but I find that this runs after any validation. So if you’re doing some regex validation that doesn’t allow leading / trailing spaces for instance, the validation will fail. It’s better to trim the whitespace first, then do the validation to avoid the user having to manually trim the spaces.

3 thoughts on “Trim Spaces in Django Forms”

  1. This code is also nice since if only whitespace is entered for a required field, the form will not accept it, which is what is expected most of the time.

    1. Yes, it sure will.

      from django.forms import ModelForm
      from django.forms import ValidationError
      from django.forms import FileField
      # Django 1.6 Version
      class BaseModelForm(ModelForm):
      # strip leading or trailing whitespace
      def _clean_fields(self):
      for name, field in self.fields.items():
      # value_from_datadict() gets the data from the data dictionaries.
      # Each widget type knows how to retrieve its own data, because some
      # widgets split data over several HTML fields.
      value = field.widget.value_from_datadict(self.data, self.files,
      self.add_prefix(name))
      try:
      if isinstance(field, FileField):
      initial = self.initial.get(name, field.initial)
      value = field.clean(value, initial)
      else:
      if isinstance(value, basestring):
      value = field.clean(value.strip())
      else:
      value = field.clean(value)
      self.cleaned_data[name] = value
      if hasattr(self, 'clean_%s' % name):
      value = getattr(self, 'clean_%s' % name)()
      self.cleaned_data[name] = value
      except ValidationError as e:
      self._errors[name] = self.error_class(e.messages)
      if name in self.cleaned_data:
      del self.cleaned_data[name]
      # Django 1.7 Version
      # (makes use of new add_error API – https://docs.djangoproject.com/en/1.7/ref/forms/api/#django.forms.Form.add_error)
      class BaseModelForm(ModelForm):
      # strip leading or trailing whitespace
      def _clean_fields(self):
      for name, field in self.fields.items():
      # value_from_datadict() gets the data from the data dictionaries.
      # Each widget type knows how to retrieve its own data, because some
      # widgets split data over several HTML fields.
      value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
      try:
      if isinstance(field, FileField):
      initial = self.initial.get(name, field.initial)
      value = field.clean(value, initial)
      else:
      if isinstance(value, basestring):
      value = field.clean(value.strip())
      else:
      value = field.clean(value)
      self.cleaned_data[name] = value
      if hasattr(self, 'clean_%s' % name):
      value = getattr(self, 'clean_%s' % name)()
      self.cleaned_data[name] = value
      except ValidationError as e:
      self.add_error(name, e)

      view raw
      basemodelform.py
      hosted with ❤ by GitHub

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s