在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()
方法将数据存储入库。