Django笔记四十二之model使用validator验证器
本文首发于公众号:Hunter后端
这一篇笔记介绍一下 model 里的 validator 验证器。
首先,这是个什么东西呢?
在 model 的第四篇笔记里,我们介绍了字段的一些属性,比如是否允许为空,varchar 类型的字段的最大长度等。
一般在存储前,我们要手动对数据进行一些校验,比如判断前端传入的字段是否为空,传入的字符最大长度是否超过我们规定的长度等。
而 validator 验证器就给我们提供了一个简便的方式可以在存储数据前自动进行校验。
以下是本篇笔记目录:
- 自定义验证器
- 引用验证器
- 校验函数
- 测试校验函数
- 系统验证器介绍
1、自定义验证器
我们下面会在 model 中调用一个验证器,它的作用是只允许保存偶数,如果是奇数则会引发 ValidationError。
示例如下:
from django.core.exceptions import ValidationError
def validate_even(value):
if value % 2 != 0:
raise ValidationError(f"{value} is not an even number")
如上所示,一个简单的验证器就完成了,它是一个函数,我们可以手动调用,传入奇数或者偶数尝试,传入偶数不会发生什么,但是传入奇数则会引发一个 ValidationError 的报错。
2、引用验证器
定义好一个验证器之后,我们在 model 中引入。
我们这里新建一个 model,名为 TestValidate:
class TestValidate(models.Model):
even_field = models.IntegerField(default=0, validators=[validate_even])
如上,一个验证器的引入就完成了,当我们在尝试对数据进行保存的时候,比如创建一条数据:
TestValidate.objects.create(even_field=1)
传入的数据值为 1,是不合法的,但是却可以保存,为什么呢?
这里介绍一下触发验证器的机制。
虽然我们在 model 里引入了验证器,但是 Django 系统并不会自动触发,而需要我们进行手动去触发校验操作。
我们在下一节介绍一下进行校验的四个函数:
- clean_fields()
- clean()
- validate_unique()
- full_clean()
3、校验函数
前面介绍到需要在保存前手动调用校验函数,先介绍一下四个校验函数
1.clean_fields(exclude=None)
接收 exclude 参数,参数类型为列表,列表元素为字段名称,表示传入的字段不进行校验,如果不传该参数,则默认对 model 的所有字段进行校验。
这个函数的操作是,校验 model 里中所有不合法的字段数据,比如没有设置允许为空,但字段的值为空,以及包括设置了 validators 参数的字段。
比如前面我们设置了 even_field 字段只允许保存偶数,那么在 save() 操作前,调用 clean_fields() 函数,则会引发 validate_even 的报错。
2.clean()
默认是一个空函数,用于我们继承重写一些校验操作,我们可以自定义一些 model 的限制需求,比如,它可以进行不同字段间的关联校验
3.validate_unique(exclude=None)
验证的是字段数据是否违反唯一性约束,其实也就是获取 model 里所有包含唯一性约束的字段,然后去数据库里查询是否包含同样的数据,如果存在,则引发验证报错。
唯一性约束包含 unique,unique_for_date,unique_for_year,unique_for_month 等,接收 exclude 参数,和 clean_fields() 函数一致,exclude 为不进行校验的字段
4.full_clean(exclude=None, validate_unique=True)
所以我们在进行 model 的 save() 操作前,可以根据我们的需要进行相应的校验操作
也可以直接调用 full_clean() 函数,这个函数会依次调用 clean_fields,clean,和 validate_unique 函数。
full_clean() 接收两个参数,一个 exclude,接收不校验的字段列表,一个validate_unique,为布尔型数据,表示是否需要进行唯一性校验
4、测试校验函数
下面我们挨个对校验函数进行处理测试操作。
首先重新设置一下 model:
# blog/models.py
from django.core.exceptions import ValidationError
from django.db import models
def validate_even(value):
if value % 2 != 0:
raise ValidationError(f"{value} is not an even number")
class TestValidate(models.Model):
even_field = models.IntegerField(default=0, validators=[validate_even])
name = models.CharField(unique=True, max_length=20, default=None)
1. 测试clean_fields
测试这个函数,我们只需要在给实例化后的 model 调用这个函数即可:
test_1 = TestValidate.objects.create(even_field=2, name="abc")
test_2 = TestValidate()
test_2.even_field = 1
test_2.name = "abc"
test_2.clean_fields()
在 test_2 调用 clean_fields() 后,系统会校验 TestValidate 实例化后所有字段的的不合法数据,以及额外的校验操作,即 validators 中定义的校验逻辑
比如在这里 even_field = 1 会被验证不通过,返回一个报错
clean_fields() 函数可以接收 exclude 参数,可用于传入不进行校验的字段名称列表,比如这里我们设置:
test_2.clean_fields(exclude=["even_field"])
那么即便 even_field 的字段值不合法,也会顺利保存。
2. 测试validate_unique
在这里我们设置了 name 字段为 unique 唯一性约束,也就是说在 TestValidate 表里 name 字段不能存在相同的值
前面我们创建了一条 name = "abc" 的值,接着我们设置 test_2.name = "abc",然后执行:
test_2.name = "abc"
test_2.validate_unique()
系统会获取 TestValidate 里所有设置了 unique 的字段,然后获取字段对应的值去数据库进行唯一性校验,在我们上面的例子里设置 name="abc" 是不通过的。
3. 测试clean
系统提供了 clean() 函数,可用于我们创建自定义的验证操作
比如,我们设置当 even_field = 4 且 name="张三" 的时候,这条数据就是不合法的,我们可以如此先设置 clean() 函数:
class TestValidate(models.Model):
even_field = models.IntegerField(default=0, validators=[validate_even])
name = models.CharField(unique=True, max_length=20, default=None)
def clean(self):
if self.even_field == 4 and self.name == "张三":
raise ValidationError("指定 even_field 和 name 不合法")
再执行:
from blog.models import TestValidate
test_3 = TestValidate()
test_3.even_field = 4
test_3.name = "张三"
test_3.clean()
4. 测试full_clean
如果我们想在 save() 前都调用一遍上面介绍的校验函数,可以直接执行 full_clean(),它会按照顺序挨个调用 clean_fields、clean、validate_unique
full_clean() 接收两个参数,一个 exclude,接收不校验的字段列表,一个validate_unique,为 布尔型数据,确定是否需要进行唯一性校验
5. 重写save()
前面我们会在每次进行 save() 前都手动执行校验函数,我们可以重写 save(),这样在每次创建和保存一个 model 实例的时候,就不需要手动调用我们前面的校验函数了,操作示例如下:
class TestValidate(models.Model):
even_field = models.IntegerField(default=0, validators=[validate_even])
name = models.CharField(unique=True, max_length=20, default=None)
def save(self, *args, **kwargs):
self.clean_fields()
self.clean()
self.validate_unique()
super(TestValidate, self).save(*args, **kwargs)
而 full_clean() 可以直接调用这三个校验函数,所以上面等效于:
def save(self, *args, **kwargs):
self.full_clean()
super(TestValidate, self).save(*args, **kwargs)
清空表数据后,我们可以进行下面的测试:
from blog.models import TestValidate
test_1 = TestValidate.objects.create(even_field=2, name="abc")
test_2 = TestValidate.objects.create(even_field=2, name="abc") # 会报校验的错误
test_3 = TestValidate()
test_3.even_field=3
test_3.name = "def"
test_3.save() # 报校验的错误
6. 继承BaseModel
我们上面的操作是基于单个 model 的 save() 操作,如果我们要对每个 model 都实现这种自动进行校验的操作,那么则需要对每个 model 都进行这种 save() 的继承重写操作
如果想要实现每个 model 自动实现这种校验的操作,我们可以编写一个 BaseModel,在 BaseModel 里重写 save() 操作,然后每个 model 都继承 BaseModel,就可以实现我们的目的了。
class BaseModel(models.Model):
class Meta:
abstract = True
def save(self, *args, **kwargs):
self.full_clean()
super(BaseModel, self).save(*args, **kwargs)
class TestValidate(BaseModel):
even_field = models.IntegerField(default=0, validators=[validate_even])
name = models.CharField(unique=True, max_length=20, default=None)
这种操作也可以用于添加基础字段,比如我们想为每个 model 都添加 updated_time 和 created_time 作为基础字段,用于记录数据写入和更新时间,可以在 BaseModel 里添加:
class BaseModel(models.Model):
updated_time = models.DateTimeField(auto_now=True)
created_time = models.DateTimeField(auto_now_add=True)
class Meta:
abstract = True
def save(self, *args, **kwargs):
self.full_clean()
super(BaseModel, self).save(*args, **kwargs)
5、系统验证器介绍
前面介绍的是自定义的验证器,以及如何使用,其实Django系统里为我们实现了很多基础的验证器:
- EmailValidator 验证邮箱格式
- MaxValueValidator 验证最大值
- MinValueValidator 验证最小值
- MaxLengthValidator 验证最大长度
- MinLengthValidator 验证最小长度
- RegexValidator 验证正则表达式
我们设置的 model 如下:
class TestValidate(BaseModel):
even_field = models.IntegerField(default=0, validators=[validate_even])
name = models.CharField(unique=True, max_length=20, default=None)
email = models.CharField(max_length=100, default="", validators=[EmailValidator(message="email不合法")])
count = models.IntegerField(default=8, validators=[MaxValueValidator(limit_value=20), MinValueValidator(limit_value=5)])
char_str = models.CharField(max_length=100, validators=[MaxLengthValidator(limit_value=90), MinLengthValidator(limit_value=20)], default="")
telephone = models.CharField(max_length=11, validators=[RegexValidator("1[345678]\d{9}")], default="")
用上了上面这几个自带的验证器,接下来我们对 email,count,char_str,telephone 几个字段设置不合法的值进行创建:
TestValidate.objects.create(
even_field=2,
name="abc",
email="12314234",
count=25,
char_str="abcd",
telephone="122282883"
)
然后会发现从 email 到 telephone 字段都报了字段值不合法的错,我们将其挨个修正为 model 里符合校验规则的数据即可正常创建数据了。
如果想获取更多相关文章,可扫码关注阅读:

Django笔记四十二之model使用validator验证器的更多相关文章
- Django笔记三十二之session登录验证操作
本文首发于公众号:Hunter后端 原文链接:Django笔记三十二之session登录验证操作 这一篇笔记将介绍 session 相关的内容,包括如何在系统中使用 session,以及利用 sess ...
- java之jvm学习笔记六-十二(实践写自己的安全管理器)(jar包的代码认证和签名) (实践对jar包的代码签名) (策略文件)(策略和保护域) (访问控制器) (访问控制器的栈校验机制) (jvm基本结构)
java之jvm学习笔记六(实践写自己的安全管理器) 安全管理器SecurityManager里设计的内容实在是非常的庞大,它的核心方法就是checkPerssiom这个方法里又调用 AccessCo ...
- 论文阅读笔记四十二:Going deeper with convolutions (Inception V1 CVPR2014 )
论文原址:https://arxiv.org/pdf/1409.4842.pdf 代码连接:https://github.com/titu1994/Inception-v4(包含v1,v2,v4) ...
- 【Unity 3D】学习笔记四十二:粒子特效
粒子特效 粒子特效的原理是将若干粒子无规则的组合在一起.来模拟火焰,爆炸.水滴,雾气等效果. 要使用粒子特效首先要创建,在hierarchy视图中点击create--particle system就可 ...
- VSTO 学习笔记(十二)自定义公式与Ribbon
原文:VSTO 学习笔记(十二)自定义公式与Ribbon 这几天工作中在开发一个Excel插件,包含自定义公式,根据条件从数据库中查询结果.这次我们来做一个简单的测试,达到类似的目的. 即在Excel ...
- 深度学习课程笔记(十二) Matrix Capsule
深度学习课程笔记(十二) Matrix Capsule with EM Routing 2018-02-02 21:21:09 Paper: https://openreview.net/pdf ...
- Django笔记四之字段属性
这篇笔记介绍的 field options,也就是 字段的选项属性. 首先,关于 model,是数据库与 python 代码里的一个映射关系,每一个 model 是django.db.models.M ...
- Django笔记三十之log日志记录详解
本文首发于公众号:Hunter后端 原文链接:Django笔记三十之log日志的记录详解 这一节介绍在 Django 系统里使用 logging 记录日志 以下是一个简单的 logging 模块示例, ...
- NeHe OpenGL教程 第四十二课:多重视口
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 网站开发进阶(四十二)巧用clear:both
网站开发进阶(四十二)巧用clear:both 前言 我们在制作网页中用div+css或者称xhtml+css都会遇到一些很诡异的情况,明明布局正确,但是整个画面却混乱起来了,有时候在IE6下看的很正 ...
随机推荐
- 第一章 Linux系统编程
Linux基础命令 ctrl + l //快速清屏 rm 文件名 //删除文件,rm *.o表示删除所有.o后缀的文件 mkdir 目录名 //创建一个目录 touch 文件名 //创建一个文件 tr ...
- 容器卡在terminate状态无法删除
1. pod卡在terminate状态无法删除.一般是lxcfx 卡住 或者 logcounter组件进程读容器数据盘分区导致的 2. 验证一下我们的猜测 cat /sys/fs/fuse/conn ...
- ASP.NET Web API Demo OwinSelfHost 自宿主 Swagger Swashbuckle 在线文档
新建Web API工程 选Empty,勾选Web API,不要选择Web API,那样会把MVC勾上,这里不需要MVC Web API工程属性 XML文件用于生成在线文档 新建Windows服务作为W ...
- SpringCloud Alibaba技术栈(二)Nacos服务治理
源码-笔记:Code for Github 第二章 Nacos服务治理 1. 模块设计与实现 ①首先创建maven项目,此项目作为父工程.把src文件夹删掉,修改pom文件,添加依赖版本控制,控制子模 ...
- AtCoder Beginner Contest 197(Sponsored by Panasonic) Person Editorial
A - Rotate 先输出第二和第三个字符,然后再输出第一个字符即可 B - Visibility 以 \((x,y)\) 作为起点向4个方向探索不是 # 的点,注意一下会在\((x,y)\)重复计 ...
- 【调试】kprobes(一)基本概念
简介 开发人员在内核或者模块的调试过程中,往往会需要要知道其中的一些函数有无被调用.何时被调用.执行是否正确以及函数的入参和返回值是什么等等. 比较简单的做法是在内核代码对应的函数中添加日志打印信息, ...
- 实时渲染前沿研究:在浏览器上实现了Facebook提出的DLSS算法
大家好,我基于WebNN在浏览器上实现了2020年Facebook提出的Neural-Supersampling-for-Real-time-Rendering算法.它是一个用于实时渲染的神经网络超采 ...
- 机器学习-无监督机器学习-SVD奇异值分解-24
[POC] 1. 奇异值分解的本质 特征值分解只能够对于方阵提取重要特征, Ax=λx λ为特征值 x为对应的特征向量 奇异值分解可以对于任意矩阵: 注意看中间的矩阵是一个对角矩阵,颜色越深越起作用- ...
- CentOS7挂载webdav添加开机启动
CentOS7挂载webdav添加开机启动 一.安装davfs2 yum install davfs2 二.挂载 1.新建挂载位置 mkdir -p /guazai chmod +x /guazai ...
- [转帖]nginx反向代理时保持长连接
https://www.cnblogs.com/liufarui/p/11075630.html ·[场景描述] HTTP1.1之后,HTTP协议支持持久连接,也就是长连接,优点在于在一个TCP连接上 ...