我们都知道,在关系数据库中,为了保证数据完整性,我们都会使用一个叫做触发器的玩意。今天我就基于Django信号机制实现类似触发器的效果,在此之前我先简单介绍一下触发器。

触发器

触发器(trigger)是数据库提供给程序员和数据分析员来保证数据完整性的一种方法,它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作(insert,delete,update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。

一般情况下,常用的触发器总共有 6 种——增加数据之前的触发器、增加数据之后的触发器、删除数据之前的触发器、删除数据之后的触发器、修改数据之前的触发器、修改数据之后的触发器。

触发器的优点

触发器可通过数据库中的相关表实现级联更改,不过,通过级联引用完整性约束可以更有效地执行这些更改。触发器可以强制比用 CHECK 约束定义的约束更为复杂的约束。与 CHECK 约束不同,触发器可以引用其它表中的列。例如,触发器可以使用另一个表中的 SELECT 比较插入或更新的数据,以及执行其它操作,如修改数据或显示用户定义错误信息。触发器也可以评估数据修改前后的表状态,并根据其差异采取对策。一个表中的多个同类触发器(INSERT、UPDATE 或 DELETE)允许采取多个不同的对策以响应同一个修改语句。

慎用触发器

触发器功能强大,轻松可靠地实现许多复杂的功能,为什么又要慎用呢。触发器本身没有过错,但由于我们的滥用会造成数据库及应用程序的维护困难。在数据库操作中,我们可以通过关系、触发器、存储过程、应用程序等来实现数据操作…… 同时规则、约束、缺省值也是保证数据完整性的重要保障。如果我们对触发器过分的依赖,势必影响数据库的结构,同时增加了维护的复杂程度。

Django 信号机制

Django 包含一个当事件发生在这个框架内的其他地方有助于多个应用模块获得通知的“信号调度器”。当一些事件发生时,允许一个发送方给一群接收方发送信号,Django 内置的信号机制有很多,具体的大家可以参考:

https://docs.djangoproject.com/zh-hans/3.0/topics/signals/。

下面我们就通过创建一个基于 Django 的学生信息管理系统来通过信号机制实现类似触发器的效果。

学生信息管理系统

我主要是为了给大家演示效果,系统弄的尽量简单,数据库总共两个表:

  1. 学生表:ID、姓名、班级

  2. 班级表:ID、名称、学生人数

其中的关系很简单:一个班级对应多个学生,一个学生只对应一个班级。

我们主要实现学生和班级这两块数据的增删改查,但其中需要注意以下 4 点:

  1. 班级表中的学生人数字段默认为 0,不可以随意更改

  2. 删除班级表中的一条数据的时候,其对应的学生表中的所有数据都要删除

  3. 增加一条学生数据的时候,需要在对应的班级表中把学生数量+1

  4. 删除一条学生数据的时候,需要在对应的班级表中把学生数量-1

新建项目

新建项目可以参考文档用命令,也可以直接用 PyCharm,我这里直接使用 PyCharm 来创建 Django 项目。点击 Create New Project,如图所示。

然后跳转到如图所示的界面,点击 Django,并设置项目路径和解释器,完成之后点击 CREATE。

等待一会之后项目就创建完成了,点击左下角的 Terminal,如图所示。

然后输入命令 python manage.py startapp student 并回车,如图所示。

我们会发现项目内多出来一个叫做 student 的目录,如图所示。

定义模型

我们接下来就去 models.py 定义模型,代码如下:

 from django.db import models# Create your models here.class Grade(models.Model):    name = models.CharField(max_length=255, verbose_name='名称')    student_number = models.PositiveSmallIntegerField(default=0, editable=False, verbose_name='学生人数')    class Meta:        verbose_name = verbose_name_plural = '班级'    def __str__(self):        return self.nameclass Student(models.Model):    name = models.CharField(max_length=255, verbose_name='姓名')    grade = models.ForeignKey(Grade, models.CASCADE, verbose_name='班级')    class Meta:        verbose_name = verbose_name_plural = '学生'    def __str__(self):        return self.name

这段代码除了“增加一条学生数据的时候,对应班级表中学生人数字段+1”和“删除一条学生数据的时候,对应班级表中学生人数字段-1”这两个要求之外的其他要求都实现了。

实现类似触发器的效果

接下来就来着重讲解这两个需求的实现,实现这两个需求大家很容易想到触发器,但是触发器最好还是慎用,我这里直接使用信号来代替触发器。信号主要位于 django.db.models.signals 模块中,其中有 pre_save(增加数据之前)、post_save(增加数据之后)、pre_delete(删除数据之前)、post_delete(删除数据之后)……

增加数据的触发器

我们先来实现增加数据的触发器,增加数据我们可以使用 pre_save 或者 post_save 信号,在这里我用 pre_save 来实现,代码如下:

 # noinspection PyUnusedLocal@receiver(pre_save, sender=Student)def pre_save_student(sender, instance, **kwargs):    grade = instance.grade    grade.student_number += 1    grade.save()

删除数据的触发器

接下来我们就来实现删除数据的触发器,删除数据我们可以通过 pre_delete 或者 post_delete 来实现。在这里我用 pre_delete 来实现,代码如下:

 # noinspection PyUnusedLocal@receiver(pre_delete, sender=Student)def pre_delete_student(sender, instance, **kwargs):    grade = instance.grade    grade.student_number -= 1    grade.save()

接下来给出 models.py 的完整代码:

 from django.db import modelsfrom django.db.models.signals import pre_save, pre_deletefrom django.dispatch import receiver# Create your models here.class Grade(models.Model):    name = models.CharField(max_length=255, verbose_name='名称')    student_number = models.PositiveSmallIntegerField(default=0, editable=False, verbose_name='学生人数')    class Meta:        verbose_name = verbose_name_plural = '班级'    def __str__(self):        return self.nameclass Student(models.Model):    name = models.CharField(max_length=255, verbose_name='姓名')    grade = models.ForeignKey(Grade, models.CASCADE, verbose_name='班级')    class Meta:        verbose_name = verbose_name_plural = '学生'    def __str__(self):        return self.name# noinspection PyUnusedLocal@receiver(pre_save, sender=Student)def pre_save_student(sender, instance, **kwargs):    grade = instance.grade    grade.student_number += 1    grade.save()# noinspection PyUnusedLocal@receiver(pre_delete, sender=Student)def pre_delete_student(sender, instance, **kwargs):    grade = instance.grade    grade.student_number -= 1    grade.save()

配置项目

配置项目我们首先激活模型,在 settings.py 中的 INSTALLED_APPS 列表中增加一个名为'student.apps.StudentConfig'的元素,如图所示。

激活模型之后我们就需要进行数据库迁移了。在之前的 Terminal 里面执行按顺序执行下面两个命令:

python manage.py makemigrations

python manage.py migrate

如图所示。

接下来就是创建一个管理员账号,在 Terminal 下执行命令python manage.py createsuperuser,然后按照提示输入信息就行了。

然后点击 PyCharm 右上角的类似于播放的按钮运行程序。

接下来打开浏览器,地址栏输入:http://127.0.0.1:8000/admin,会发现进入了一个登录页面,用之前创建的管理员账号登录,登陆之后我们会发现并没有学生和班级。我们还要去 admin.py 中注册模型,注册代码如下:

 from django.contrib import adminfrom.models import Grade, Student# Register your models here.admin.site.register(Grade)admin.site.register(Student)

注册完成之后像之前一样重新运行项目,登陆之后如图所示。

我们可以发现学生和班级已经有了,为了测试我们先增加一个班级,增加完成之后查看数据库可以发现数据库中确实有这条记录,如图所示。

接下来我们增加一个学生,增加学生之后,我们看一下班级表中对应的学生人数字段是不是从 0 变成了 1,如图所示。

班级表中的学生人数字段确实从 0 变成了 1,所以说增加数据的触发器测试通过。

接下来我们测试一下删除数据的触发器,我们就把之前增加的学生数据删掉,看看班级表中对应的学生人数字段是不是又变回到 0,删除之后刷新数据库的结果如图所示。

班级表中的学生人数字段确实从 1 变成了 0,所以说删除数据的触发器测试通过。

总结

不管是增加数据的触发器还是删除数据的触发器,我们都可以通过 Django 信号机制来实现类似的效果,比在数据库中定义触发器简单太多了,而且大幅度地降低了数据库的维护成本。

今天的文章有不懂的可以后台回复“加群”,备注:小陈学Python,不备注可是会被拒绝的哦~!

创建一个delete触发器_基于 Django 信号机制实现类似触发器的效果相关推荐

  1. echarts python源码_基于Django快速集成Echarts代码示例

    1.在线定制下载echarts 2.创建一个django项目或者在已有的项目 配置文件中确保数据库配置.static配置.与添加项目名到INSTALLED_APPS下. 配置静态文件目录static, ...

  2. 使用vue创建一个遮罩组件_用于输入遮罩的另一个Vue组件

    使用vue创建一个遮罩组件 语音输入蒙版 (vue-input-mask) Yet another Vue component for input masking. Based on react-in ...

  3. 创建一个storageevent事件_事件循环:微任务和宏任务

    浏览器中 JavaScript 的执行流程和 Node.js 中的流程都是基于 事件循环 的. 理解事件循环的工作方式对于代码优化很重要,有时对于正确的架构也很重要. 在本章中,我们首先介绍有关事物工 ...

  4. python做一个考试系统_1218Python基于Django在线考试系统设计

    如果你满意这个设计可以分享到: 以下是本计算机毕业设计介绍,若对此项目感兴趣,请联系客服QQ:344245001 [运行截图请往下看]编程语言:Android.iOS.C#.Asp/Asp.net.J ...

  5. python 创建一个空向量_Python之Django系列-创建第一个应用-5

    上一篇:Python之Django系列-创建第一个应用-4 这一章我们会讲到视图层怎么与数据库操作并返回数据到模板层进行渲染最终显示在页面上 投票应用基本上会有这么几个视图 问题列表页 问题详情页 问 ...

  6. 用labview设计jk触发器_基于LabVIEW的基本触发器设计.doc

    您所在位置:网站首页 > 海量文档 &nbsp>&nbsp计算机&nbsp>&nbspLabview 基于LabVIEW的基本触发器设计.doc15页 ...

  7. sh脚本每天创建一个文件夹_我每天创建一个月的视频。 这就是发生的事

    sh脚本每天创建一个文件夹 At the end of 2019 I promised that 2020 would be all about my YouTube channel. So that ...

  8. vscode如何创建一个go项目_如何用手机创建一个网站

    如何用手机创建网站?其实正确的说法是如何创建一个手机网站才对,因为很难用手机去制作网站,很不方便.一般是用电脑模拟手机去建网站. 我们知道现在很多人上网都是通过手机上网,所以我们自己建网站时,也要学会 ...

  9. python如何创建一个文件夹_利用Python怎么创建一个文件夹

    利用Python怎么创建一个文件夹 发布时间:2020-12-08 14:48:04 来源:亿速云 阅读:91 作者:Leah 这期内容当中小编将会给大家带来有关利用Python怎么创建一个文件夹,文 ...

最新文章

  1. “一百万行Python代码对任何人都足够了”
  2. jQuery 遍历 - closest() 方法
  3. 【解决方案】chrome打开新标签页自动打开chrome://newtab并且跳转到谷歌香港
  4. pyqt5窗口 样式 背景
  5. OpenGL ES之3D渲染旋转的贴图立方体
  6. Educational Codeforces Round 72 (Rated for Div. 2)
  7. 用vhdl语言设计一个小游戏_用最直白的设计语言营造梦想的办公空间
  8. pdf 字体和图片抽取
  9. HTML可以替代CSS的所有功能,CSS-用Divs替换HTML表
  10. java中if的嵌套循环_嵌套的多个“Next变量”if then循环
  11. C语言基础程序题及答案(适合学完C基础的人练练手)
  12. JavaScript刷新当前页面的五种方式
  13. Unity游戏开发学习路线
  14. CSS 实现水晶按钮特效 - 来自 www.codesc.net
  15. iOS15.4 Beta4 新测试版推送,新增反跟踪功能
  16. Cyberdog——小米四足机器人测评
  17. java图片编辑器,Java图片编辑工具thumbnailator
  18. 计算机网络:P4.3-网络层(下)
  19. Unity画面像素化shader
  20. 计算机校准颜色,直观:如何在Win7计算机中校准显示器|计算机显示器颜色校准...

热门文章

  1. flask websocket json_Win10环境下使用Flask配合Celery异步推送实时/定时消息/2020年最新攻略...
  2. 组装台式电脑配置清单_萌新攒机必备!多价位台式电脑配置清单!
  3. 春节海报背景素材,喜庆中国味!
  4. 设计师值得学习的分类网站
  5. UI干货素材模板|从做好网页头部内容设计开始!
  6. java qrious 二维码中文无反应_来了来了,今天的苹果限免应用刚刚出炉,8款APP在App Store限时免费啦!手慢无~...
  7. KVM Virtio: An I/O virtualization framework for Linux(Linux虚拟IO框架)
  8. Java与C语言混合编程
  9. python QTreeWidgetItem下面有几个子tree_非常干货:Python 探针实现原理
  10. python爬取网页时返回http状态码HTTP Error 418以及如何查看自己的User-Agent