2014-08-31 53 views
2

無效值我有一個繼承了一些模型,看起來像這樣:Django的model.full_clean()允許IntegerField

Class A(models.Model): 
    some_text = models.CharField(max_length=100) 
    #other fields, not important 

Class B(A): 
    some_int = models.IntegerField(blank=True, null=True, validators=[MinValueValidator(1), MaxValueValidator(1000)]) 

然後我火了Django的外殼並執行以下操作:

>>> obj = B() 
>>> obj.some_text = 'foo' 
>>> obj.some_int = 'bar' 
>>> obj.full_clean() 

,自然我得到:

>>> ValidationError: {'some_int': [u"'bar' value must be an integer."]} 

好。然後:

>>> obj.some_int = ' ' #whitespace 
>>> obj.full_clean() 

我也得到:

>>> ValidationError: {'some_int': [u"' ' value must be an integer."]} 

完美。但後來我嘗試空字符串:

>>> obj.some_int = '' #empty string 
>>> obj.full_clean() 

沒有ValidationError提高,但如果我嘗試保存對象:

>>> obj.save() 

我得到:

>>> ValueError: invalid literal for int() with base 10: '' 

這是怎麼回事?這是正確的行爲? Django如何檢查值是否爲有效整數?

我真的不想自定義我的模型的clean()函數來檢查這個,但它開始看起來像我沒有選擇。

編輯:Django 1.6.5,Python 2.7.6,Windows 7 64位。

回答

4

的這種現象的原因是在評價方法clean_fields:

def clean_fields(self, exclude=None): 
    """ 
    Cleans all fields and raises a ValidationError containing message_dict 
    of all validation errors if any occur. 
    """ 
    if exclude is None: 
     exclude = [] 

    errors = {} 
    for f in self._meta.fields: 
     if f.name in exclude: 
      continue 
     # Skip validation for empty fields with blank=True. The developer 
     # is responsible for making sure they have a valid value. 
     raw_value = getattr(self, f.attname) 
     if f.blank and raw_value in f.empty_values: 
      continue 
     try: 
      setattr(self, f.attname, f.clean(raw_value, self)) 
     except ValidationError as e: 
      errors[f.name] = e.error_list 

    if errors: 
     raise ValidationError(errors) 
+0

Welp ...你說得對。我想這有一個很好的理由,我目前無法完全理解。儘管如此,看到它明確寫道我負責驗證空白字段的'blank = True'使得解決方案感覺不那麼髒亂。謝謝。 – 2014-08-31 21:32:34

0

那是因爲你允許你的字段爲空(也是空)。 所以它是好的,它是有效的。

如果你不希望它是這樣,只是刪除blank=True選項,或將其更改爲blank=False

+2

如果「它是好的,它是有效的」,那麼爲什麼一個異常升高,當我嘗試保存對象?如果我將該值設置爲無,它工作正常。當我調用save_()時調用full_clean()並且沒有值錯誤時,它不會引發驗證錯誤。這隻發生在一個空字符串。 – 2014-08-31 21:17:45

2

,因爲你有blank=True你得到此行爲。我同意你的看法,你看到的行爲很奇怪 - 這是Django 模型驗證與表單驗證綁定的事實的一個症狀,即使原則上它們可以是分開的。

假設你實際上需要blank=Truenull=True,我不會擔心這個。表單將做正確的事情(將表單中的空字符串轉換爲數據庫中的NULL值),並且模型和數據庫實際上不會讓您保存無效值。唯一的問題是,如果您有不涉及Django表單的數據輸入,則錯誤將被拋出save()時間,而不是在full_clean()時間。

當然,如果您不想允許該字段的值爲NULL,只需設置blank=False, null=Falsefull_clean()就會像您期望的那樣抱怨空字符串。

+0

不幸的是,該字段必須保持爲'blank = False,null = False'...並且我確實有不涉及Django表單的數據輸入。看起來我必須自己檢查一下。感謝您的見解。 – 2014-08-31 21:28:49