在Django中,对数据进行校验有两种方式:一种是通过Form校验,一种是通过Model校验。在此,我对Model中的校验方法做下记录。
示例之前补充以下几点:
1、Django数据校验方式分为以下三步:
Model.clean_fields() 验证字段基本规则比如长度格式等;
Model.clean() 可自定义验证条件和报错信息;
Model.validate_unique() 为验证添加的唯一性约束。
2、此三步验证通过调用full_claen(exclude=None, validate_unique=True)来依次执行。
exclude:可以用来指定不需要执行校验的field。ModelForm也利用这个参数来将field排除。
validate_unique:用来指定是否需要执行Model.validate_unique()。
3、而full_clean()又是通过调用is_valid()方法来执行。
4、save()执行的时候是不会自动调用full_clean()来进行校验的。
校验应该在save()执行之前完成,你可以先在form进行校验,也可以在model中进行校验。但是,你必须确保通过这两个校验之后的数据是绝对没有问题的“干净”数据,然后再调用save()方法将数据存储入库。
5、校验中的错误处理
我们使用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): if self.status == 'draft' and self.pub_date is not None: # raise ValidationError({'pub_date': _('Draft entries may not have a publication date.')}) raise ValidationError({'pub_date': 'Draft entries may not have a publication date.'}) ...
如何指定多个field的校验错误信息:
class Article(models.Model): ... def clean(self): if self.status == 'draft' and self.pub_date is not None: raise ValidationError({'pub_date': 'Draft entries may not have a publication date.', 'creator': 'Creator can't be null'}) ...
如何指定全局性校验错误信息:
class Article(models.Model): ... def clean(self): if self.status == 'draft' and self.pub_date is not None: raise ValidationError('Draft entries may not have a publication date.') ...
进入正题:
一、如何使用验证器:
在验证某个字段的时候,在模型或者自定义form表单中传递一个 validators 参数用来指定验证器,进一步对数据进行过滤。
或者,通过model中的 Field类型 或者一些参数就可以指定。
比如 EmailVa本文来源gao@daima#com搞(%代@#码@网&lidator ,我们可以通过 指定字段类型为EmailField 来指定。
比如 MaxValueValidator ,我们可以通过 max_value 、max_length参数来指定。
class Interview(models.Model): feedback = models.TextField(max_length=1024, validators=[MinLengthValidator(20, message='不少于20字')], verbose_name='面试反馈') mail = models.EmailField(max_length=64, blank=True, null=True, verbose_name='邮箱') age= models.IntegerField(max_value=64, blank=True, null=True, verbose_name='年龄')