16👍
Model cleaning has to be called (it’s not automatic) so place some self.full_clean()
in your save method.
http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.full_clean
As for your form, you need to return the stripped cleaned data.
return self.cleaned_data['name'].strip()
Somehow I think you just tried to do a bunch of stuff that doesn’t work. Remember that forms and models are 2 very different things.
Check up on the forms docs on how to validate forms
http://docs.djangoproject.com/en/dev/ref/forms/validation/
super(Employee), self.clean().strip() makes no sense at all!
Here’s your code fixed:
class Employee(models.Model):
"""(Workers, Staff, etc)"""
name = models.CharField(blank=True, null=True, max_length=100)
def save(self, *args, **kwargs):
self.full_clean() # performs regular validation then clean()
super(Employee, self).save(*args, **kwargs)
def clean(self):
"""
Custom validation (read docs)
PS: why do you have null=True on charfield?
we could avoid the check for name
"""
if self.name:
self.name = self.name.strip()
class EmployeeForm(ModelForm):
class Meta:
model = Employee
def clean_name(self):
"""
If somebody enters into this form ' hello ',
the extra whitespace will be stripped.
"""
return self.cleaned_data.get('name', '').strip()
27👍
When you’re using a ModelForm instance to create/edit a model, the model’s clean() method is guaranteed to be called. So, if you want to strip whitespace from a field, you just add a clean() method to your model (no need to edit the ModelForm class):
class Employee(models.Model):
"""(Workers, Staff, etc)"""
name = models.CharField(blank=True, null=True, max_length=100)
def clean(self):
if self.name:
self.name = self.name.strip()
I find the following code snippet useful- it trims the whitespace for all of the model’s fields which subclass either CharField or TextField (so this also catches URLField fields) without needing to specify the fields individually:
def clean(self):
for field in self._meta.fields:
if isinstance(field, (models.CharField, models.TextField)):
value = getattr(self, field.name)
if value:
setattr(self, field.name, value.strip())
Someone correctly pointed out that you should not be using null=True in the name declaration. Best practice is to avoid null=True for string fields, in which case the above simplifies to:
def clean(self):
for field in self._meta.fields:
if isinstance(field, (models.CharField, models.TextField)):
setattr(self, field.name, getattr(self, field.name).strip())
- [Django]-How to explicitly set django_language in django session
- [Django]-Open the file in universal-newline mode using the CSV Django module
- [Django]-Django multi-database routing
7👍
If you have so many data-fields to be trimmed, why not try extending CharField?
from django.db import models
from django.utils.translation import ugettext_lazy as _
class TrimCharField(models.CharField):
description = _(
"CharField that ignores leading"
" and trailing spaces in data")
def get_prep_value(self, value)
return trim(super(TrimCharField, self
).get_prep_value(value))
def pre_save(self, model_instance, add):
return trim(super(TrimCharField, self
).pre_save(model_instance, add))
UPDATE:
For Django versions <= 1.7 if you want to extend field, you are to use models.SubfieldBase metaclass. So here it will be like:
class TrimCharField(six.with_metaclass(
models.SubfieldBase, models.CharField)):
- [Django]-How to get the first element and the last element using django , Location.objects.all()
- [Django]-Warning: cannot find svn location for distribute==0.6.16dev-r0
- [Django]-Serving static media during Django development: Why not MEDIA_ROOT?
7👍
Django 1.9 offers a simple way of accomplishing this. By using the strip
argument whose default is True, you can make sure that leading and trailing whitespace is trimmed. You can only do that in form fields though in order to make sure that user input is trimmed. But that still won’t protect the model itself. If you still want to do that, you can use any of the methods above.
For more information, visit https://docs.djangoproject.com/en/1.9/ref/forms/fields/#charfield
- [Django]-How can I render a tree structure (recursive) using a django template?
- [Django]-How use Django with Tornado web server?
- [Django]-How do you set DEBUG to True when running a Django test?
3👍
I’m handling this in views as a decorator. I’m also truncating field values that exceed a CharField max_length value.
from django import forms
from django import models
from django.db.models.fields import FieldDoesNotExist
from django.utils.encoding import smart_str
class CleanCharField(forms.CharField):
"""Django's default form handling drives me nuts wrt trailing
spaces. http://code.djangoproject.com/attachment/ticket/6362
"""
def clean(self, value):
if value is None:
value = u''
value = smart_str(value).strip()
value = super(forms.CharField, self).clean(value)
return value
def truncate_charfield(model):
"""decorator to truncate CharField data to model field max_length.
Apply to the clean method in views Form:
@truncate_charfield(MyModel)
def clean(self):
...
"""
def wrap(f):
def wrapped_f(*args):
f(*args)
d = args[0].cleaned_data
for field in model._meta.fields:
try:
mf = model._meta.get_field(field.name)
if isinstance(mf, models.CharField) and field.name in d:
d[field.name] = d[field.name][:mf.max_length]
except FieldDoesNotExist:
pass
return d
return wrapped_f
return wrap
- [Django]-Django FileField upload is not working for me
- [Django]-Django filter many-to-many with contains
- [Django]-Determine complete Django url configuration
0👍
If you’re still not on Django 1.9+ shame on you (and me) and drop this into your form. This is similar to @jeremy-lewis’s answer but I had several problems with his.
def clean_text_fields(self):
# TODO: Django 1.9, use on the model strip=True
# https://docs.djangoproject.com/en/1.9/ref/forms/fields/#charfield
from django.forms.fields import CharField
cd = self.cleaned_data
for field_name, field in self.fields.items():
if isinstance(field, CharField):
cd[field_name] = cd[field_name].strip()
if self.fields[field_name].required and not cd[field_name]:
self.add_error(field_name, "This is a required field.")
def clean(self):
self.clean_text_fields()
- [Django]-Python Django Global Variables
- [Django]-Django: using blocks in included templates
- [Django]-Displaying a Table in Django from Database