Django笔记四十二之model使用validator验证器

这篇具有很好参考价值的文章主要介绍了Django笔记四十二之model使用validator验证器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文首发于公众号:Hunter后端

原文链接:Django笔记四十二之model使用validator验证器

这一篇笔记介绍一下 model 里的 validator 验证器。

首先,这是个什么东西呢?

在 model 的第四篇笔记里,我们介绍了字段的一些属性,比如是否允许为空,varchar 类型的字段的最大长度等。

一般在存储前,我们要手动对数据进行一些校验,比如判断前端传入的字段是否为空,传入的字符最大长度是否超过我们规定的长度等。

而 validator 验证器就给我们提供了一个简便的方式可以在存储数据前自动进行校验。

以下是本篇笔记目录:

  1. 自定义验证器
  2. 引用验证器
  3. 校验函数
  4. 测试校验函数
  5. 系统验证器介绍

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 系统并不会自动触发,而需要我们进行手动去触发校验操作。

我们在下一节介绍一下进行校验的四个函数:

  1. clean_fields()
  2. clean()
  3. validate_unique()
  4. 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验证器文章来源地址https://www.toymoban.com/news/detail-746753.html

到了这里,关于Django笔记四十二之model使用validator验证器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Django笔记四十三之使用uWSGI部署Django系统

    Django笔记四十三之使用uWSGI部署Django系统

    本文首发于公众号:Hunter后端 原文链接:Django笔记四十三之使用uWSGI部署Django系统 目前部署 Django 的方式一般来说是使用 Nginx + uWSGI + Django 来实现。 处理流程是,当一个请求发送过来会先经过 Nginx,如果是静态文件请求,Nginx 这一层直接处理,如果是后端动态接口,则会发送

    2024年02月05日
    浏览(14)
  • Django笔记四十之运行Django环境的python脚本

    Django笔记四十之运行Django环境的python脚本

    本文首发于公众号:Hunter后端 原文链接:Django笔记四十之运行Django环境的python脚本 这一篇笔记介绍如何在 Django 中运行脚本。 假设说我们要实现一个功能,需要获取 blog.models.Blog 这张表里的总数且使用 print() 输出。 如果代码逻辑很短,且是一次性执行的操作,我们可以在系

    2024年02月04日
    浏览(9)
  • Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作

    Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作

    本文首发于公众号:Hunter后端 原文链接:Django笔记四十四之Nginx+uWSGI部署Django以及Nginx负载均衡操作 这一篇笔记介绍如何使用 Nginx + uWSGI 来部署 Django。 上一篇笔记中有介绍直接使用 uWSGI 作为 web 服务器来部署 Django,这一篇笔记介绍如何使用 Nginx 来部署。 使用 Nginx 来部署相

    2024年02月05日
    浏览(13)
  • 【微信小程序】-- 使用 npm 包 - API Promise化(四十二)

    【微信小程序】-- 使用 npm 包 - API Promise化(四十二)

    💌 所属专栏:【微信小程序开发教程】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘   大家好,又见面了,

    2023年04月09日
    浏览(5)
  • Django笔记(五):模型models

    Django中的模型对应数据库中的一张表格。 player.py 每个模型需要继承models类,如上Player模型定义了一个整形字段idx。常见字段类型有: 字段 描述 IntegerField 整形 FloatField 浮点型 CharField 字符串类型 TextField 长文本类型 BooleanField 布尔类型 每个字段可定义参数: 参数 取值 描述

    2024年01月22日
    浏览(3)
  • django中的model的一些笔记

    model中外键关联中的related_name属性,可以在外键表中作为筛选条件,也就是反过来在外键表中使用。例如下面的使用WarehouseStockRecord就是外键表 2.django中的Q()对象用于构建复杂查询条件的工具 在查询时,可以将Q对象作为参数传递给filter()方法,以实现复杂的查询条件

    2024年02月16日
    浏览(6)
  • es 笔记二之基础查询

    es 笔记二之基础查询

    本文首发于公众号:Hunter后端 原文链接:es笔记二之基础查询 这一篇笔记介绍 es 的基础查询。 基础查询包括很多,比如排序,类似数据库 limit 的操作,like 操作,与或非等,对于这些操作,我会在介绍他们的用法之后加上对应的数据库 sql 便于理解。 注意: 下面的操作都在

    2024年02月05日
    浏览(6)
  • Python笔记二之多线程

    Python笔记二之多线程

    本文首发于公众号:Hunter后端 原文链接:Python笔记二之多线程 这一篇笔记介绍一下在 Python 中使用多线程。 注意 :以下的操作都是在 Python 3.8 版本中试验,不同版本可能有不同之处,需要注意。 本篇笔记目录如下: 概念 多线程的使用示例 daemon run() 线程对象的属性和设置

    2024年02月03日
    浏览(8)
  • Mariadb高可用MHA (四十二)

    Mariadb高可用MHA (四十二)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、概述     1.1 概念  1.2 组成   1.3  特点   1.4  工作原理 二、构建MHA 2.1 ssh免密登录 2.2 主从复制 2.3 MHA安装  2.3.1所有节点安装perl环境 2.3..2 node 2.3.3 manager (只在mgt上装) 2.3.4 测试 2.

    2024年02月12日
    浏览(10)
  • 第四十二回:DateRangePickerDialog Widget

    我们在上一章回中介绍了DatePickerDialog Widget相关的内容,本章回中将介绍 DateRangePickerDialog Widget .闲话休提,让我们一起Talk Flutter吧。 我们在这里说的 DateRangePickerDialog 是一种弹出窗口,只不过窗口的内容固定显示为日期,它和DatePickerDialog类似,也是用来让用户选择日期,选择

    2024年02月07日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包