2011-02-18 73 views
14

如何從Django中的charField的末尾去除空格(trim)?(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() 

已修改:更新了代碼到我的最新版本。我不確定我做錯了什麼,因爲它仍然沒有剝離空白(修剪)名稱字段。

回答

10

模型清潔必須被調用(它不是自動的),因此請在您的保存方法中放置一些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() makes no sense at all!

這是你的代碼固定:

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

我仍然有問題 - 它仍然沒有剝離空白(微調)。我試着按照你發佈的教程,以及你在save方法中調用full_clean()的想法。我正在努力去理解a)EmployeeForm被調用了嗎? b)是否調用了full_clean()方法?我在我的問題中更新了我的代碼示例。我希望我能指出正確的方向。 – zardon 2011-02-18 18:14:08

+0

讓我複製並粘貼您的代碼並進行修改。 – 2011-02-18 18:26:26

+0

感謝您的幫助,我對Django/Python非常陌生;所以對於我應該如何實現各種功能的各種錯誤和誤解表示歉意。 – zardon 2011-02-18 19:24:06

3

我的意見作爲裝飾處理這個。我還截斷了超過CharField max_length值的字段值。

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 
19

當您使用ModelForm實例創建/編輯模型時,保證調用模型的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() 

我發現下面的代碼片段useful-它修剪空白的所有而無需分別指定領域的子類無論是CharField或文本字段(所以這也捕捉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()) 

有人正確地指出,你不應該使用空=真在名稱聲明中。最好的做法是避免空=真字符串字段,在這種情況下,上述簡化爲:

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

如果你要修剪這麼多的數據字段,爲什麼不嘗試延長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: 對於的Django版本< = 1。7如果你想擴展字段,你要使用models.SubfieldBase元類。因此,這裏將是這樣的:

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

的Django 1.9提供了實現該目標的簡單方法。通過使用缺省值爲True的strip參數,可以確保前後空白符被修剪。您只能在表單字段中執行此操作,以確保修剪用戶輸入。但是這仍然不能保護模型本身。如果你仍然想這樣做,你可以使用上面的任何方法。

欲瞭解更多信息,請訪問https://docs.djangoproject.com/en/1.9/ref/forms/fields/#charfield

0

如果你還沒有在Django的1.9+羞辱你(和我)拖放到表單此。這與@ jeremy-lewis的回答類似,但我遇到了幾個問題。

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