Django的信号机制解读

news2024/9/22 13:45:12

Django的信号

Django的信号机制不同于Linux的信号机制,Django 中的信号用于在框架执行操作时解耦。当某些动作发生的时候,系统会根据信号定义的函数执行相应的操作

Django的信号主要包含以下三个要素:

  • 发送者(sender):信号的发出方。
  • 信号(signal):发送的信号本身。
  • 接收者(receiver):信号的接收者。

其中接受者就是回调函数,会把这个函数注册到信号之上。当特定事件发生之后,发送者发送信号,然后执行回调函数。

Django信号的使用

查看Django Signal的源码,看到Django的信号存在以下方法

image-20230202162549086

除了上面的几个方法,还有几个属性

  • lock
  • recievers
  • sender_receivers_cache
  • use_caching

根据第一趴介绍知道,要使用Django的信号,需要满足三要素(发送者、接受者、和信号)

Django通过connect() 函数监听 信号,接受发送者发送的信号,然后执行接受者(回调函数)

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

其中

  • recievers 是接受者,本质就是一个回调函数
  • sender 是发送信号的主体,如果connect连接的时候,sender 是None(默认也是None)代表该信号接受所有发送者发送的该信号;否则只接受具体的发送者(一个Python对象,比如Django的 Model对象)
  • weak – Django 默认将信号处理程序存储为弱引用。因此,如果你的接收器是本地函数,则可能会对其进行垃圾回收。要防止这种情况发生,当你要调用 connect() 方法时请传入 weak=False。
  • dispatch_uid 在可能发送重复信号的情况下,信号接收器的唯一标识符。

具体使用方式

1、需要定义一个回调函数

def my_callback(sender, **kwargs):
    print("Request finished!")

2、把回调函数 注册到对应的信号

from django.core.signals import request_finished
request_finished.connect(my_callback)

注意这里没有指定sender,那么就是接受任意发送者哦

或者更简单的方式是使用 receiver 函数

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")

或者指定具体的发送者

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished, sender="MyTagModel")
def my_callback(sender, **kwargs):
    print("Request finished!")

==> 划重点

一般我们会把 回调函数信号注册 放到一个应用的目录下的 signals.py 文件中去

然后在该应用的 apps.py 中应用

from django.apps import AppConfig
from django.core.signals import request_finished

class MyAppConfig(AppConfig):
    ...

    def ready(self):
        # Implicitly connect signal handlers decorated with @receiver.
        from . import signals
        # Explicitly connect a signal handler.
        request_finished.connect(signals.my_callback)

这样只要改应用安装在 INSTALLED_APPS 中去,那么Django就能识别到具体的信号(包括自定义的信号)以及进行信号的处理(因为已经自动通过 connect进行监听 )

为啥会自动监听呢,当然是 Django的 AppConfig 下的 ready() 函数的作用

自定义信号

首先有个核心点需要明确

所有的信号都是 django.dispatch.Signal 的实例。

比如这里新增一个发送邮件的信号,每次新增Post之后,发送邮件给相关订阅的人

# demoapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver

from .models import Post

@receiver(post_save, sender=Post)
def send_mail(sender, instance, created, **kwargs):
	if created:
		print(f"current instance {instance}")
		print("Try to send mail to subscriber")

然后把信号导入到 appConfig 的ready() 函数中去

# demoapp/apps.py

from django.apps import AppConfig


class DemoappConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'demoapp'

    def ready(self):
        import demoapp.signals

然后我们在admin注册Post之后,新增Post,在命令行日志中就能看到

current instance DemoPost First One
Try to send mail to subscriber
[02/Feb/2023 13:47:29] "POST /admin/demoapp/post/add/ HTTP/1.1" 302 0

还有另外一个 主动发送信号的方式

1、先定义回调函数 callback_func

2、定义一个信号 mail_send_signal = Signal()

3、回调函数注册到信号 mail_send_signal.connect(callback_func)

3、主动发送信号 mail_send_signal.send(sender=xxx, **kwargs)

具体的代码实现,可以手动尝试哦,实践出真知嘛~

扩展:查看Django信号的接受者

Django内置信号的reciever查看

(kfzops) [ 23-02-02 16:04 ] [ colinspace.com ] python manage.py shell
Python 3.9.6 (default, Jul 16 2021, 13:41:17)
[Clang 12.0.5 (clang-1205.0.22.11)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.db.models.signals import post_migrate
>>> post_migrate.receivers
[(('django.contrib.auth.management.create_permissions', 4304618416), <weakref at 0x10232b310; to 'function' at 0x10231d1f0 (create_permissions)>), ((4331786592, 4304618416), <weakref at 0x102581e00; to 'function' at 0x10231d160 (create_contenttypes)>)]

扩展:Django内置信号

Django内置了很多有用的信号,大概有以下几类,可以作为了解。

模型相关的信号

  • pre_init
  • post_init
  • pre_save
  • post_save
  • pre_delete
  • post_delete
  • m2m_changed
  • class_prepared

其中

1、pre_init/post_init 分别会在模型的__init__() 方法调用 之前/之后发出

2、pre_save/post_save 分别会在模型的save() 方法调用 之前/之后发出

3、pre_delete/post_delete 分别会在模型的delete() 方法调用 之前/之后发出

4、m2m_changed 严格意义上来说是由ManyToManyField 字段发生变化的时候发出的

5、class_prepared 比较特殊一般不建议用

django-admin 发出的信号,确切的说是 Django admin在执行 python manage.py migrate的时候发出的信号

  • pre_migrete
  • post_migrate

顾名思义,不做过多解释

请求响应信号,也就是Django 发起request和响应response的信号

  • request_started
  • request_finished
  • get_request_exception

另外还有几个特殊的信号

1、setting_changed 只有当运行测试用例的时候发出

2、template_render 当测试系统渲染模板的时候发出

3、connect_created 当数据库连接启动的时候,数据库管理器发出

参考文档

1、 https://docs.djangoproject.com/zh-hans/4.1/topics/signals/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/196343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络隔离后的文件传输怎么解决?深度解析4种主流方案

网络隔离对于很多企业来说并不陌生&#xff0c;出于数据安全的考虑&#xff0c;为了隔离有害的网络和可能的网络攻击&#xff0c;越来越多的企业在内部进行了网络隔离。隔离的形态和方式有多种&#xff0c;总体上主要以物理隔离和逻辑隔离为主。网络隔离可以一定程度上甚至彻底…

功能测试环境搭建

前言新年好呀大家&#xff0c;大家都复工了吗~小编已经在搬砖中了&#x1f636;在假期中小编学习了一点功能测试方面知识&#xff0c;打算写篇博客记录下来&#xff0c;希望这篇博客可以帮到需要的朋友。流程图一、测试计划测试计划需要在所有的测试工作之前进行&#xff0c;一…

HTTP协议(2)

1)当我们在浏览器上面输入一个搜狗搜索的网址之后&#xff0c;浏览器就会给搜狗的服务器发送了一个HTTP请求&#xff0c;这样咱们的搜狗的服务器就会返回一个HTTP响应&#xff1b; 2)当这个响应结果被浏览器解析之后&#xff0c;就展示成了我们目前所看到的页面内容&#xff0c…

20230203英语学习

What Is a Dog Anyway? 狗的争议性起源&#xff1a;到底怎么定义“狗” The geographer Jared Diamond has called domestication the worst mistake humans ever made. And yet, the first domestication — the turning of wolves into dogs — was an impressive feat.Hu…

java对象的比较

上一章中关于PriorityQueue的使用要注意&#xff1a; 1. PriorityQueue中放置的元素必须要能够比较大小&#xff0c;不能插入无法比较大小的对象&#xff0c;否则会抛出 ClassCastException异常 2. 不能插入null对象&#xff0c;否则会抛出NullPointerException 3. 没有容量限制…

C/C++ 内存泄漏检测

C/C 内存泄漏检测内存泄漏的两个问题使用宏定义覆盖 malloc 和 free 函数使用 hook 钩子最近学习了 C/C 内存泄漏检测的相关知识&#xff0c;写博客记录一下。 内存泄漏的两个问题 是否有内存泄漏&#xff1f;内存泄漏是在代码的哪一行&#xff1f; 检测内存泄漏主要从上面两…

数据库系统概念 | 第十三章:事务管理 | 事务特性(ACID)| 冲突可串行化

文章目录&#x1f4da;事务的概念&#x1f407;事务定义&#x1f407;事务界定&#x1f407;事务特性&#xff08;ACID&#xff09;&#x1f407;一个简单的事务模型&#x1f4da;存储器结构&#x1f4da;事务的原子性和持久性&#x1f407;几种常见的事务状态&#x1f407;事务…

MDA260-16-ASEMI整流模块MDA260-16

编辑-Z MDA260-16在MDA封装里采用的2个芯片&#xff0c;是一款单臂共阳极整流模块。MDA260-16的浪涌电流Ifsm为11000A&#xff0c;漏电流(Ir)为15mA&#xff0c;其工作时耐温度范围为-40~150摄氏度。MDA260-16采用GPP硅芯片材质&#xff0c;里面有2颗芯片组成。MDA260-16的电性…

转行大数据开发应该怎么学习

转行进入大数据&#xff0c;首先需要了解的就是大数据是做什么&#xff0c;工作内容&#xff0c;然后就是找个完整的学习路线跟着去学习了&#xff0c;大数据的学习内容也是不少的~ 简单来说&#xff0c;分为6步&#xff0c;大数据开发入门&#xff0c;大数据核心基础&#xf…

【iHooya】2023年2月2日寒假作业解析

#include <bits/stdc.h> using namespace std;int main() {int n, r; //n个人&#xff0c;r个水龙头cin >> n >> r;int time[n];for (int a 0; a < n; a){cin >> time[a];}sort(time, time n); //时间从小到大排序int minx 0, lt_time[10001], j…

程序全过程:觉醒(序)

程序全过程序很惭愧&#xff0c;写了几年的程序&#xff0c;技术的功力没有太大增长&#xff0c;只是在项目的熟悉程度上有不少进步。因为上学时没好好学&#xff0c;很多现在工作中用到的编程技能都是在工作中边学边用的&#xff0c;相当于一直处于临时抱佛脚的状态&#xff0…

iptables端口复用

环境&#xff1a; 攻击主机&#xff1a;Kali -- 192.168.218.135 目标主机&#xff1a;RHEL8 -- 192.168.218.129 什么是端口复用 端口复用是指不同的应用程序使用相同端口使用相同端口进行通讯。 场景 目标主机是Linux系统&#xff0c;目标主机防火墙有严格的限制&#…

【FAQ】申请运动健康服务验证环节常见问题及解答

华为 HMS Core 运动健康服务&#xff08;HUAWEI Health Kit&#xff09;提供原子化数据开放。应用在获取用户数据授权后&#xff0c;可通过接口访问运动健康数据&#xff0c;对用户数据进行读写等操作&#xff0c;为用户提供运动健康类数据服务。 开发者应用在开发和测试阶段访…

SGI STL二级空间配置器源码剖析(2)

接着上回&#xff0c;这节开始说allocte内存分配的实现 目录 allocate源码流程&#xff1a; _S_refill 的实现&#xff1a; _S_chunk_alloc的实现&#xff1a; deallocate&#xff1a; reallocate&#xff1a; 二级空间配置器的逻辑步骤&#xff1a;假如现在申请n个字节&…

选择计算机专业,必看的10条自学建议

选择了计算机专业&#xff0c;很迷茫&#xff0c;没事&#xff01;&#xff01;博主整理了关于学习计算机的十条自学经验&#xff0c;从各个方面阐述了如何学习计算机专业。 1、学会使用Google搜索&#xff0c;放弃百度&#xff0c;你会发现Google 会搜出更多有用的答察&#x…

车规级MCU缺货持续2年多,上海航芯持续加码市场

MCU是传统燃油车的重要芯片之一&#xff0c;在电动车领域&#xff0c;MCU也有着广泛的应用&#xff0c;且随着汽车电子化的持续发展&#xff0c;车用MCU的市场规模还将随之持续扩大&#xff0c;据 IC insights 数据显示&#xff0c;至2026年&#xff0c;全球车规级MCU的市场规模…

C++——函数重载,引用

✅<1>主页&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;C &#x1f525;<3>创作者&#xff1a;我的代码爱吃辣 ☂️<4>开发环境&#xff1a;Visual Studio 2022 &#x1f4ac;<5>前言&#xff1a;补充C语言语法的不足&#…

【Kubernetes】记录一次K8S容器内程序OOM排查过程:unable to create new native thread

文章目录项目背景问题初现问题排查问题定位问题解决项目背景 基于k8s的容器化kafka PaaS管理平台&#xff0c;业务团队申请kafka&#xff0c;通过一系列操作&#xff0c;封装crd&#xff0c;调用operator创建集群&#xff0c;当然还包括其他功能、topic管理、group管理、监控告…

年后上来面试了13家企业软件测试岗位,面试题整理

软件测试面试&#xff0c;800多道高频面试真题&#xff0c;随便刷。&#xff08;希望能帮助大家&#xff09;项目的测试流程 1. 拿到需求文档后&#xff0c;写测试用例 2. 审核测试用例 3. 等待开发包 4. 部署测试环境 5. 冒烟测试&#xff08;网页架构图&#xff09; 6.…

CSS中height:100vh和height:100%的区别是什么?

CSS中height:100vh和height:100%的区别 首先&#xff0c;我们得知道1vh它表示的是当前屏幕可见高度的1/100&#xff0c;而1%它表示的是父元素长或者宽的1%&#xff08;可以这么理解&#xff1f;&#xff09; 1、对于设置height:100%;有下面几种情况&#xff1a; &#xff08…