在Django中,對數據進行校驗有兩種方式:一種是經過Form中校驗,一種是經過Model校驗。在次,我對Model中的校驗方法作下記錄。django
全部內容都是基於Django1.10的官網文檔整理而來ide
Model中的校驗是經過調用Model.full_clean()
方法來執行的。包括在Form中也會對objects進行校驗,也是經過調用Model.full_clean()
的方式來進行的。可是,一般的狀況下咱們並不須要本身調用Model.full_clean()
方法。ui
當你使用ModelForm的時候,Model.full_clean()
將會在你調用is_valid()
方法的時候對ModelForm中全部的field進行校驗。只有當你想要本身特別的處理校驗的報錯信息,或者是想要校驗在ModelForm中沒有包含的field時才須要來本身調用full_clean()
這個方法。code
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
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
校驗model fields - Model.clean_fields()
it
校驗整個model - Model.clean()
io
校驗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(exclude=None)
這個方法將會校驗排除exclude中指定的,model中的全部field。當它校驗失敗的時候,會拋出ValidationError異常。
若是你想要自定義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(exclude=None)
最後,full_clean()將會檢查model中的unique的限制。它在校驗失敗的時候會拋出ValidationError異常。
值得注意的是:上面屢次提到,在執行save()
方法的時候,是不會進行數據校驗的。校驗應該在save()
執行以前完成,你能夠先在form進行校驗,也能夠在model中進行校驗。可是,你必須確保經過這兩個校驗以後的數據是絕對沒有問題的「乾淨」數據,而後再調用save()
方法將數據存儲入庫。