Django信号机制详解:内置信号参数与自定义信号实现
本文详细介绍Django中信号(signals)的使用机制。涵盖pre_save、post_save等五大类内置信号及其参数详解,演示通过connect和@receiver装饰器两种注册方式。重点讲解自定义信号的创建、注册及send与send_robust方法在异常处理上的区别,帮助开发者实现应用解耦。
Django信号机制概述
正文
在日常开发中,常需在执行特定操作前后获取通知并执行自定义逻辑,此时可使用Django的信号(signals)机制。Django内置的信号分发器允许应用解耦,当框架内发生特定事件时,会通知所有注册了该信号的回调函数,从而在回调中执行所需操作。
Django内置信号详解
一、Django内置信号
Django内置信号主要覆盖数据表操作、migrate命令执行、URL请求(request/response)、测试用例运行以及数据库连接五大场景。
内置信号分类与参数
Model signals
pre_init # model执行构造方法前,触发
post_init # model执行构造方法后,触发
pre_save # model执行save对象保存前,触发
post_save # model执行save对象保存前,触发
pre_delete # model执行delete对象删除前,触发
post_delete # model执行delete对象删除前,触发
m2m_changed # model使用多对多字段操作第三张表前后,触发
class_prepared # 程序启动时,检测已注册的model类,对每个类,触发
Management signals
pre_migrate # 执行migrate前,触发
post_migrate # 执行migrate后,触发
Request/response signals
request_started # 请求到来前,触发
request_finished # 请求结束后,触发
got_request_exception # 请求异常后,触发
Test signals
setting_changed # 使用test测试修改配置文件,触发
template_rendered # 使用test测试渲染模板时,触发
Database Wrappers
connection_created # 创建数据库连接时,触发
1. 常用内置信号参数介绍
(1) django.db.models.signals.pre_save
pre_save处理程序的参数介绍
参数名 参数介绍 sender 模型类 instance 保存的实际实例(保存后的model数据对象) raw 布尔值; True如果模型完全按照提供的方式保存。不应该查询/修改数据库中的其他记录,因为数据库可能尚未处于一致状态 using 正在使用的数据库别名 update_fields 要传递给更新的字段集model.save(),或者None 如果update_fields未传递给它save()
(2) django.db.models.signals.post_save
post_save处理程序的参数介绍
参数名 参数介绍 sender 模型类 instance 保存的实际实例 created 布尔值; True如果创建了新记录(True表示数据创建) raw 布尔值; True如果模型完全按照提供的方式保存。不应该查询/修改数据库中的其他记录,因为数据库可能尚未处于一致状态 using 正在使用的数据库别名 update_fields 要传递给更新的字段集model.save(),或者None 如果update_fields未传递给它save()
(3) django.db.models.signals.pre_delete
pre_delete处理程序的参数介绍
参数名 参数介绍 sender 模型类 instance 要删除的实际实例 using 正在使用的数据库别名
(4) django.db.models.signals.post_delete
post_delete处理程序的参数介绍
参数名 参数介绍 sender 模型类 instance 要删除的实际实例(该对象将不再存在于数据库中,因此请谨慎对待此实例) using 正在使用的数据库别名
更多信号参数介绍请参考https://docs.djangoproject.com/zh-hans/2.1/ref/signals/
内置信号监听方法
2. 内置信号监听方法
对于Django内置信号,只需注册指定信号,程序执行相应操作时即可自动触发注册函数。编写好接收器(receiver function)用于处理信号回调后,需将接收器连接到信号,连接方式包括手动连接和使用receiver装饰器两种。
手动连接实现方法:
from django.db.models.signals import post_delete
def my_callback(sender, **kwargs):
print(sender)
print("信号已接收")
post_delete.connect(my_callback) # 信号连接接收器,用于收到信号的回调,如果想要指定某个表对象,直接指定sender
# connect参数接收
"""
receiver - 将连接到此信号的回调函数。回调函数名,不带括号
sender - 指定从中接收信号的特定发送方。
weak - Django默认将信号处理程序存储为弱引用。因此,如果您的接收器是本地功能,它可能被垃圾收集。为了防止这种情况,请weak=False在调用信号connect()方法时通过。
dispatch_uid - 在可能发送重复信号的情况下信号接收器的唯一标识符。
"""
receiver装饰器实现方法:
from django.dispatch import receiver
from django.db.models.signals import post_delete
from app.models import UCenter
@receiver(post_delete, sender=UCenter) # post_delete指定信号触发类型,sender指定到具体对象
def delete_u2user(sender, instance, **kwargs): # instance表示被删除的对象
print(sender, instance)
更多信号操作相关问题参考文档https://docs.djangoproject.com/zh-hans/2.1/topics/signals/
自定义信号实现
二、自定义信号使用
1. 定义信号
自定义信号的定义与注册
from django.dispatch import Signal
test_signal = Signal(providing_args=["name", "age"]) # 声明一个test_signal的信号,提供给接收器name跟age两个参数(可自定义参数)
2. 注册信号
def my_callback(sender, **kwargs):
print(sender)
print("信号已接收")
test_signal.connect(my_callback) # 注册信号,指定接收器为my_callback
3. 触发信号
from xxx import test_signal
test_signal.send(sender='test', name='zzq', age='18') # 触发信号,发送name,age参数信息
信号触发与异常处理
触发信号时,可选择使用Signal.send或Signal.send_robust两种方法。
send()与send_robust()在处理接收器功能引发的异常时存在差异。
send()不捕获接收器抛出的任何异常,仅允许错误传播。因此,若发生错误,并非所有接收器都能收到信号通知。
send_robust()捕获所有从Python Exception类派生的错误,并确保所有接收器均收到信号通知。若发生错误,错误实例将作为元组对返回给引发错误的接收器。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对本站的支持。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









