(Django) 从charField中去除空格

22 投票
6 回答
42799 浏览
提问于 2025-04-16 12:04

我想知道如何在Django中去掉charField字段末尾的空格(也就是修剪空格)?

这是我的模型,你可以看到我尝试过添加清理方法,但这些方法从来没有被执行。

我也试过用 name.strip()models.charField().strip(),但这些也不管用。

有没有办法让charField字段自动去掉空格呢?

谢谢。

from django.db import models
from django.forms import ModelForm
from django.core.exceptions import ValidationError
import datetime

class Employee(models.Model):
    """(Workers, Staff, etc)"""
    name                = models.CharField(blank=True, null=True, max_length=100)

    def save(self, *args, **kwargs):
        try:
            # This line doesn't do anything??
            #self.full_clean()
            Employee.clean(self)
        except ValidationError, e:
            print e.message_dict

        super(Employee, self).save(*args, **kwargs) # Real save

    # If I uncomment this, I get an TypeError: unsubscriptable object
    #def clean(self):
    #   return self.clean['name'].strip()

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'Employees'

    class Admin:pass


class EmployeeForm(ModelForm):
    class Meta:
        model = Employee

    # I have no idea if this method is being called or not  
    def full_clean(self):       
        return super(Employee), self.clean().strip()
        #return self.clean['name'].strip()

编辑:我更新了我的代码到最新版本。我不太确定我哪里做错了,因为名字字段还是没有去掉空格。

6 个回答

7

如果你有很多数据字段需要处理,为什么不试着扩展一下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))

更新:对于Django版本小于等于1.7的情况,如果你想扩展字段,你需要使用models.SubfieldBase这个元类。这样做的话,代码会像这样:

class TrimCharField(six.with_metaclass(
    models.SubfieldBase, models.CharField)):
27

当你使用一个ModelForm实例来创建或编辑一个模型时,模型的clean()方法一定会被调用。所以,如果你想去掉某个字段的空格,只需要在你的模型里添加一个clean()方法(不需要修改ModelForm类):

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()

我觉得下面这段代码很有用——它会去掉所有模型字段的空格,只要这些字段是CharField或TextField类型(这也包括URLField字段),而不需要单独指定每个字段:

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())

有人正确指出,在字段声明中不应该使用null=True。最佳做法是避免在字符串字段中使用null=True,这样上面的代码就可以简化为:

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())
16

模型清理需要手动调用(不是自动的),所以在你的保存方法里加上 self.full_clean()
http://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.full_clean

至于你的表单,你需要返回经过处理的干净数据。

return self.cleaned_data['name'].strip()

我觉得你可能尝试做了一些不太管用的事情。记住,表单和模型是两回事。

查看一下表单的文档,了解如何验证表单:
http://docs.djangoproject.com/en/dev/ref/forms/validation/

super(Employee), self.clean().strip() 完全没有意义!

这是修正后的代码:

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()

撰写回答