• 3分钟看懂Python后端必须知道的Django的信号机制!


    概念

    django自带一套信号机制来帮助我们在框架的不同位置之间传递信息。也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(receivers)。

    (感觉就很像Qt的信号与槽机制)

    信号系统包含以下三要素:

    • 发送者-信号的发出方
    • 信号-信号本身
    • 接收者-信号的接受者

    Django内置了一整套信号,下面是一些比较常用的:

    在ORM模型的save()方法调用之前或之后发送信号

    django.db.models.signals.pre_save
    django.db.models.signals.post_save
    

    在ORM模型或查询集的delete()方法调用之前或之后发送信号。

    django.db.models.signals.pre_delete
    django.db.models.signals.post_delete
    

    当多对多字段被修改时发送信号。

    django.db.models.signals.m2m_changed
    

    当接收和关闭HTTP请求时发送信号。

    django.core.signals.request_started
    django.core.signals.request_finished
    

    这就很方便了,想象一下这样一个情景,我们引入了一个第三方的Django库,他会创建模型,我们想要在不修改他的代码的情况下,在他创建模型的时候同时修改其他表的数据,那么这时候信号机制就能派上用场了。

    简单使用例子

    信号监听有两种方式,一种是Signal.connect()方法,一种是装饰器。

    Signal.connect()方法

    方法原型:

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

    参数:

    • receiver :当前信号连接的回调函数,也就是处理信号的函数。
    • sender :指定从哪个发送方接收信号。
    • weak : 是否弱引用
    • dispatch_uid :信号接收器的唯一标识符,以防信号多次发送。

    装饰器法

    from django.core.signals import request_finished
    from django.dispatch import receiver
    
    @receiver(request_finished)
    def my_callback(sender, **kwargs):
        print("Request finished!")
    

    可以给receiver添加sender参数来筛选接收哪个模型产生的信号,比如:

    from django.db.models import signals
    from django.dispatch import receiver
    
    @receiver(signals.post_save, sender=MyModel)
    def demo_callback(sender: MyModel, instance: MyModel, **kwargs):
        pass
    

    注意要读取传入的模型对象一定是要用instance参数,不是sendersender是一个类型!

    设置dispatch_uid参数防止重复信号

    为了防止重复信号,可以设置dispatch_uid参数来标识你的接收器,标识符通常是一个字符串,如下所示:

    from django.core.signals import request_finished
    
    request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")
    

    断开信号

    在满足某些条件下,我们不再需要监听信号,可以选择断开信号。

    Signal.disconnect()用来断开信号的接收器。和Signal.connect()中的参数相同。如果接收器成功断开,返回True,否则返回False。

    Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)[source]
    

    后记

    最近刚入职项目很多特别的忙,也学到了很多新技术,但是感觉已经好久没有时间来好好写一篇博客了,就算是本文也是短时间拼凑的,真是难呀,周末得好好整理一下最近的技术笔记。

    关于Django信号机制的更多内容(自定义信号等),可以参考官方文档。https://docs.djangoproject.com/en/3.0/topics/signals/

    PS:接下来应该会写写Django Admin方案的相关调研,emm,还有关于微信小程序的登录、支付接入的,不是什么很难的东西,但是第一次用的话处处充满坑……

    欢迎交流

    我整理了一系列的技术文章和资料,在公众号「程序设计实验室」后台回复 linux、flutter、c#、netcore、android、java、python 等可获取相关技术文章和资料,同时有任何问题都可以在公众号后台留言~

  • 相关阅读:
    Spring Boot应用程序属性
    Spring Boot Bean和依赖注入
    Spring Boot构建系统
    Spring Boot Tomcat部署
    Spring Boot引导过程
    Spring Boot快速入门
    Spring Boot简介
    eclipse中将项目打包成jar的两种方法,及其问题与解决方法
    配置Zuul代理下游的认证
    WireMock和Spring MVC模拟器
  • 原文地址:https://www.cnblogs.com/deali/p/13372922.html
Copyright © 2020-2023  润新知