Django的數據驗證(validating objects)

在Django中,對數據進行校驗有兩種方式:一種是經過Form中校驗,一種是經過Model校驗。在次,我對Model中的校驗方法作下記錄。django

全部內容都是基於Django1.10的官網文檔整理而來ide

validating objects

數據校驗的觸發:

Model中的校驗是經過調用Model.full_clean()方法來執行的。包括在Form中也會對objects進行校驗,也是經過調用Model.full_clean()的方式來進行的。可是,一般的狀況下咱們並不須要本身調用Model.full_clean()方法。ui

何時須要調用full_clean()

當你使用ModelForm的時候,Model.full_clean()將會在你調用is_valid()方法的時候對ModelForm中全部的field進行校驗。只有當你想要本身特別的處理校驗的報錯信息,或者是想要校驗在ModelForm中沒有包含的field時才須要來本身調用full_clean()這個方法。code

Model.full_clean說明

Model.full_clean(exclude=None, validate_unique=True)
Model.full_clean()內部實際上是會經過3個方法來進行不一樣層次的校驗,對於這3個方法在後面會講到。orm

參數:

可選參數exclude能夠用來指定不須要執行校驗的field。ModelForm也利用這個參數來將field排除。
參數validate_unique用來指定是否須要執行Model.validate_unique()文檔

如何檢查校驗結果:

full_clean將會按序執行3個方法,這3個方法若是校驗失敗的話,會將相關信息寫到異常的message_dict屬性中,而且拋出ValidationError異常。get

save()執行的時候是不會自動調用full_clean()來進行校驗的。input

手動校驗model的合法性:

from django.core.exceptions import ValidationError
try:
    article.full_clean()
except ValidationError as e:
    # Do something based on the errors contained in e.message_dict.
    # Display them to a user, or handle them programmatically.
    pass

3個校驗方法:

  1. 校驗model fields - Model.clean_fields()it

  2. 校驗整個model - Model.clean()io

  3. 校驗field的惟一性 - Model.validate_unique()

這幾個步驟將會在調用model的full_clean()方法時執行,流程以下:

st=>start: Model.full_clean
e=>end: return
io=>inputoutput: rais ValidationError
sub1=>subroutine: Model.clean_fields
cond1=>condition: valid
sub2=>subroutine: Model.clean
cond2=>condition: valid
sub3=>subroutine: Model.validate_unique
cond3=>condition: valid

st->sub1->cond1(yes)->sub2->cond2(yes)->sub3->cond3(yes)->e
st->sub1->cond1(no)->io
st->sub1->cond1(yes)->sub2->cond2(no)->io
st->sub1->cond1(yes)->sub2->cond2(yes)->sub3->cond3(no)->io

Model.clean_fields

Model.clean_fields(exclude=None)
這個方法將會校驗排除exclude中指定的,model中的全部field。當它校驗失敗的時候,會拋出ValidationError異常。

Model.clean

若是你想要自定義model的校驗,或者想要修改model的屬性的話,就override這個方法。例如,你可使用它來爲field自動提供一個值:

import datetime
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError(_('Draft entries may not have a publication date.'))
        # Set the pub_date for published items if it hasn't been set already.
        if self.status == 'published' and self.pub_date is None:
            self.pub_date = datetime.date.today()

當調用model的save()方法的時候,是不會調用Model.clean來進行校驗的

校驗中的錯誤處理

在上面的例子中,咱們使用了ValidationError來在Model.clean中拋出錯誤,這個錯誤信息將會存儲在以NON_FIELD_ERRORS爲key的字典中。這個key是用來存儲對於整個model中的錯誤信息的。

如何獲取校驗的錯誤信息:

from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
try:
    article.full_clean()
except ValidationError as e:
    non_field_errors = e.message_dict[NON_FIELD_ERRORS]

如何指定對於某個特定的field的校驗錯誤信息:

class Article(models.Model):
    ...
    def clean(self):
        # Don't allow draft entries to have a pub_date.
        if self.status == 'draft' and self.pub_date is not None:
            raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')})
        ...

如何指定多個field的校驗錯誤信息:

raise ValidationError({
    'title': ValidationError(_('Missing title.'), code='required'),
    'pub_date': ValidationError(_('Invalid date.'), code='invalid'),
})

Model.validate_unique說明

Model.validate_unique(exclude=None)
最後,full_clean()將會檢查model中的unique的限制。它在校驗失敗的時候會拋出ValidationError異常。

注意

值得注意的是:上面屢次提到,在執行save()方法的時候,是不會進行數據校驗的。校驗應該在save()執行以前完成,你能夠先在form進行校驗,也能夠在model中進行校驗。可是,你必須確保經過這兩個校驗以後的數據是絕對沒有問題的「乾淨」數據,而後再調用save()方法將數據存儲入庫。

相關文章
相關標籤/搜索