故事背景

最近在做的项目中都遇到使用 django 信号量,故此总结信号相关的使用。

什么是信号

Django 中内置一个 信号调度器,它可以帮助应用程序在框架中的其他地方发生某些固定操作时能够得到通知。简而言之:信号允许某些发送器通知一组接收器某些操作已经发生。当接受器接受到这一通知时可以做响应的处理。

Django 中内置的信号集

模型信号

  • 模型初始化时

    • django.db.models.signals.pre_init(模型在初始化时发出)
    • django.db.models.signals.post_init(模型在被初始化之后发出)
  • 模型 save()方法相关信号

    • django.db.models.signals.pre_save (模型在被保存之前发出)
    • django.db.model.signals.post_save(模型对象被保存之后发出)
  • 模型 delete()方法相关信号

    • dajngo.db.models.signals.pre_delete(模型被删除之前)
    • django.db.models.signals.post_delete(模型被删除之后)
  • 模型多对多(manytomanyField)字段发生更改时

    • django.db.models.signals.m2m_changed(模型中多对多字段发生改变)
  • 执行迁移之前

    • django.db.models.signals.pre_migrate(在模型迁移之前执行)
    • django.db.models.signals.post_migrate(在模型迁移之后执行)

网络请求相关

  • django 发起或者结束一个 http 请求相关信号

    • django.core.signals.request_started(django 发起一个 http 请求前)
    • django.core.signals.request_finished(django 发起一个 http 请求之后)
  • django 发送请求发生错误时
    • django.core.signals.got_request_exception(发送请求发生错误时)

Django 信号量使用

使用 Signal.connect()方法注册一个接收器函数,当发送信号时调用接收器。信号的所有接收器函数都会按照注册时的顺序一个接一个调用。

Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)

  • receiver:将连接到此信号的回调函数
  • sender:指定要从其接收信号的特定发送方
  • weak:Django 默认将信号处理程序存储为弱引用,因此如果你的接收器函数时本地函数,则可能会对其进行垃圾回收。如果想避免这种情况发生可以当你要调用 connct() 方法时传入 weak=False
  • disptch_uid:在可能发送重复信号的情况下,信号接收器的唯一标识

接受信号函数

下面我们定义一个接收函数,接受函数可以是任何 python 函数或者方法:

def my_callback(sender, **kwargs):print('hello world')

注意⚠️:该函数接受一个 sneder 参数以及关键字参数(**kwargs),所有信号处理程序都必须接受这些参数。

连接接受函数

Django 提供两种方法可以将接收器连接到信号。

  • 方式一:Signal.connet(my_callback)

    from django.core.signals import request_finishedrequest_finished.connect(my_callback)
    
  • 方式二:receiver(sigal)

    • 参数 signal:一个用于连接函数的信号包含多个信号列表
    • 接受函数和连接接受函数放在 在一起
    from django.core.signals import request_finished
    from django.dispatch import receiver@receiver(request_finished)
    def my_callback(sender, **kwargs):print('hello world')
    

    以上两种方式都能到达 my_callback 函数在每次请求完成时被调用

接受到特定发送器发送的信号

在某些情况下有些信号被发送多次,但你只对这些信号中某部分信号感兴趣。假设我们有 User 以及 Enterprise 两个 model 我们只想接受当模型 User 保存后的信号,代码如下:

from django.db.models.signals import post_save
from django.dispatch import receiver
from . models import User@receiver(post_save, sender=Udser)
# 这里的 instance 可以表示为当前变化的模型实例
def my_handel(sender, instance, **kwargs):# to do ...

防止信号重复

在某些情况下,接受器可能同时接受相同信号多次,这可能会导致接收函数被注册多次,因此对于一个信号时间调用同样多次,为防止这种相同信号被接受多次的情况发生,我们可以传递一个唯一标识符作为 dispatch_uid 参数来标识接收方函数。这个标识符通常是一个字符串,对于每个唯一 dispatch_uid 值,接受器函数值与信号绑定一次:

from django.core.signals import post_savepost_save.connect(my_callback, dispatch_uid='my_unique_identifier')

django 信号量实际使用

监听某个模型中某个字段的变化

假设我们有一个 User 模型,当我们用户名发生改变时需要重置 token,这时我们只需要监听 User 中 token 是否变化,如果变化则重置 token,使用信号来实现这一需求

# 用户模型class User(models.Model):id = models.BigIntegerField(primary_key=True)name = models.CharField(max_length=32, verbose_name='用户名')areaCode = models.CharField(max_length=10, blank=True, verbose_name='手机区号')phone = models.CharField(max_length=20, verbose_name='用户手机号', blank=True)email = models.EmailField(max_length=50, verbose_name='用户邮箱', blank=True)avatar = models.CharField(max_length=255, verbose_name='用户头像')token = models.CharField(max_length=50, verbose_name='token')
# 信号量实现以上场景from django.db.models.signals import post_init, post_save
from django.dispatch import receiverfrom . models import User@receiver(post_init, sender=User)
def init_signal(sender, instance, **kwargs):# 在模型初始化时将 name 赋值给 __origin_nameinstance.__origin_name = instance.name@receiver(post_save, sender=User)
def save_signal(sender, instance, **kwargs):# 当模型被保存时查看此时的 name 和 __origin_name 是否相等,如果不相等则重置 tokenif instance.__origin_name and instance.__origin_name != instance.name:# 重置 token

Django signals 信号总结相关推荐

  1. django的信号signals详解

    介绍: Django 提供一个了"信号分发器"机制,允许解耦的应用在框架的其它地方发生操作时会被通知到. 通俗而讲Django信号的工作原理,就是当某个事件发生的时候,会发出一个信 ...

  2. 测试django_如何像专业人士一样测试Django Signals

    测试django by Haki Benita 通过Haki Benita 如何像专业人士一样测试Django Signals (How to test Django Signals like a p ...

  3. Django的信号机制详解

    Django的信号机制详解 Django提供一种信号机制.其实就是观察者模式,又叫发布-订阅(Publish/Subscribe) .当发生一些动作的时候,发出信号,然后监听了这个信号的函数就会执行. ...

  4. django:信号机制

    文章目录 一,django信号 (一)什么是信号 (二)信号的使用场景 1,信号的直接使用场景 2,使用信号的终极目的 3,使用原则 二,如何使用信号 (一)自定义与使用信号 1,创建信号.信号发送器 ...

  5. django Signals

    前言 在平时应用中我们经常遇到比如新增加一个用户就发送短信,新增加一条留言就给我们 发送邮箱 这种需求,一般来说都可以在视图函数中完成这些操作.但是如果有多个地方都需要类似的操作,比如用户在N个应用中 ...

  6. python处理信号机制_Python的Flask框架中的signals信号机制

    Flask 提供了信号(Signals)功能,是一种消息分发机制.类似于钩子(Hooks).使用信号功能可以降低程序的耦合,分解复杂的业务模型.例如在更新了产品数据后,可以发送一个信号.当有需要对产品 ...

  7. Django的信号Signals介绍及使用

    Django提供一种信号机制.其实就是观察者模式,又叫发布-订阅(Publish/Subscribe) .当发生一些动作的时候,发出信号,然后监听了这个信号的函数就会执行.通俗来讲,就是一些动作发生的 ...

  8. Django模型信号——django.db.models.signals

    目录 一.监听信号 1.接收器函数¶ 2.连接接收器函数¶ 3.连接到特定发送器发送的信号¶ 4.防止重复信号¶ 二.定义和发送信号 1.定义信号¶ 2.发送信号¶ 三.断开信号¶ 本站相关文章: 1 ...

  9. django的 信号

    1.信号,其实就是钩子,可以在上面几种情况下定义执行某个函数,我们一般在project的__init__文件中定义,下面就是一个例子 2.用到模块需要导入,分别在下面的几个路径中 from djang ...

最新文章

  1. 判断一棵二叉树是否为AVL树
  2. Vue中使用Openlayers加载OSM(Open Street Map)显示街道地图
  3. LeetCode 2103. 环和杆(位运算)
  4. 阿里云发布第七代云服务器ECS,整机算力提升160%
  5. Mysql更新字段中部分数据的方法
  6. java的remove iterator_Java集合 iterator.remove()方法详解
  7. 网页设计师必备的35套图标(免费下载)
  8. [转载] python如何获取当前月份_Python-获取当前月的前x月月份日期
  9. 4.23上海交大PMP试题每日一题
  10. 语言缩写c-a,各国语言缩写及语言代码查询
  11. ZYJ7型转辙设备安装调试工法
  12. 增程式电动汽车建模与仿真(一)
  13. MQTT之十一 阿里云物联网平台网址
  14. HTML知识点(来自广陵散老师)
  15. citespace 版本5.6.R5无法打开, 版本为5.6.R2可以打开
  16. “财界奥斯卡”CGMA全球管理会计2021年度中国大奖榜单揭晓
  17. php仿u8系统模板_中文分词源码_7urpu8 采用php的源码实现 - 下载 - 搜珍网
  18. wxw4444bird
  19. 【笔试】店铺选址+最短路径
  20. denied git permission_git使用中遇到的Permission to xxx denied to xxx问题如何解决

热门文章

  1. python测试用例不通过发送报告_selenium+python自动化89-用例不通过的时候发送邮件...
  2. 【云服务架构】大健康之医疗智能硬件解决方案
  3. 解决Cannot fit requested classes in a single dex file
  4. 支付宝H5支付,支付页面无响应事件以及解决方案。
  5. 硬件设计MBD的困境与出路
  6. 有没有可以把照片变成卡通版的app?
  7. 使用ORACLE OCI V8版本编程,在执行PL/SQL块时,不能同时绑定标量变量和数组变量......
  8. 把数字世界带入每一辆车的华为
  9. 艺赛旗(RPA)selenium 利用 js 处理日历控件
  10. RPA学习天地:艺赛旗RPA培训产品解读(2021年7月)