目录

一、监听信号

1.接收器函数¶

2.连接接收器函数¶

3.连接到特定发送器发送的信号¶

4.防止重复信号¶

二、定义和发送信号

1.定义信号¶

2.发送信号¶

三、断开信号¶


本站相关文章:

1.在Ddjango文件和图片的删除和修改时,同步更新media的存储文件

2.Django图片字段——打开相机+压缩+水印+更改+删除

Django 包含一个“信号调度器”,它帮助已解藕的应用程序在框架中的其它地方发生操作时可以得到通知。简而言之,信号允许某些 发送器 通知一组 接收器 某些操作已经发生。当许多代码段可能对同一事件感兴趣时,它们特别有用。

Django 提供了 内置信号集 使用户代码能够获得 Django 自身某些操作的通知。其中包括一些有用的通知:

  • django.db.models.signals.pre_save & django.db.models.signals.post_save

    一个模型的 save() 方法被调用之前或之后发出。

  • django.db.models.signals.pre_delete & django.db.models.signals.post_delete

    一个模型的 delete() 方法或查询结果集的 delete() 方法被调用之前或之后发出。

  • django.db.models.signals.m2m_changed

    一个模型的 ManyToManyField 更改后发出。

  • django.core.signals.request_started & django.core.signals.request_finished

    Django 发起或结束一个 HTTP 请求后发出。

查看 内置信号文档 以获取每个信号的完整列表和说明。

你还可以 定义和发送自定义信号;见下文。

一、监听信号

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

Signal.connect(receiversender=Noneweak=Truedispatch_uid=None

参数:
  • receiver -- 将连接到此信号的回调函数。查看 接收器函数 获取更多信息。
  • sender -- 指定要从其接收信号的特定发送方。查看 连接到特定信号 获取更多信息。
  • weak -- Django 默认将信号处理程序存储为弱引用。因此,如果你的接收器是本地函数,则可能会对其进行垃圾回收。要防止这种情况发生,当你要调用 connect() 方法时请传入 weak=False
  • dispatch_uid -- 在可能发送重复信号的情况下,信号接收器的唯一标识符。查看 防止重复信号 获取更多信息。

让我们通过注册一个在每个HTTP请求完成后被调用的信号来看看这是如何工作的。我们将连接到 request_finished 信号。

1.接收器函数

首先,我们需要定义一个接收器函数。一个接收器可以是任何 Python 函数或方法:

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

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

稍后 我们将讨论发送器,但现在来看下 **kwargs 参数。所有信号都发送关键字参数,并且可以随时更改这些关键字参数。在接收 request_finished 信号时,该信号没有发送任何参数,这意味着我们可能会试图将我们的信号处理程序写成 my_callback(sender)

这是错误的——事实上,如果这样做,Django 将抛出一个错误。这是因为在任何时候,参数都可能被添加到信号中,而你的接收器必须能够处理这些新的参数。

2.连接接收器函数

有两种方法可以将接收器连接到信号。你可以选择手动连接线路:

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

或者,你可以使用一个 receiver() 装饰器:

receiver(signal

参数: signal -- 一个用于连接函数的信号或包含多个信号的列表。

以下是你如何使用装饰器连接:

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

现在,我们的 my_callback 函数将在每次请求完成时被调用。

我的代码该放在哪?

严格来说,信号处理和注册的代码可以放在任何你喜欢的地方,但是推荐避免放在应用程序的根目录和 models 模块内以尽量减少导入代码的副作用。

在实践中,信号处理程序通常定义在与之相关的应用程序的 signals 子模块中。信号接收器在你应用程序配置类的 ready() 方法中连接。如果你使用 receiver() 装饰器,在 ready() 中导入 signals 子模块。

注解

ready() 方法在测试过程中可能会多次执行,因此你可能需要 防止重复信号,尤其是当您计划在测试中发送信号时。

3.连接到特定发送器发送的信号

有些信号被多次发送,但你只对接收这些信号的某个子集感兴趣。例如,仔细考虑 django.db.models.signals.pre_save 在模型保存之前发送的信号。大多数时候,你不需要知道 任何 模型何时被保存——只需要知道某个 特定 模型何时被保存。

在这些情况下,您可以注册以接收仅由特定发送者发送的信号。在接收 django.db.models.signals.pre_save 信号时 ,发送器会是要保存的模型类,因此你就可以表明你想要某个模型发送的信号:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):...

my_handler 函数将仅在 MyModel 实例保存后被调用。

不同的信号使用不同的对象作为它们的发送者;你需要查阅 内置信号文档 了解每个特定信号的详细信息。

4.防止重复信号

在某些情况下,连接接收器到信号的代码可能被执行多次。这可能会导致接收器函数被注册多次,因此对于一个信号事件调用同样多次。例如,ready() 方法在测试期间可能被多次执行。更普遍的是,在项目的任何地方导入定义信号的模块都会发生这种情况,因为信号注册的运行次数与导入的次数相同。

如果此行为会产生问题(例如在保存模型时使用信号发送电子邮件),则传递一个唯一标识符作为 dispatch_uid 参数来标识接收方函数。这个标识符通常是一个字符串,尽管任何可散列对象都可以。最终的结果是,对于每个唯一的 dispatch_uid 值,接收器函数只与信号绑定一次:

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

二、定义和发送信号

您的应用程序可以利用信号基础设施并提供自己的信号。

何时使用自定义信号

信号是隐式函数调用,这使得调试更加困难。如果你的自定义信号的发送器和接收器都在你的项目内,最好使用显式函数调用。

1.定义信号

class Signal

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

例如:

import django.dispatchpizza_done = django.dispatch.Signal()

这声明了一个 pizza_done 信号。

2.发送信号

在 Django 中有两种发送信号的方法。

Signal.send(sender**kwargs

Signal.send_robust(sender**kwargs

要发送信号,调用 Signal.send() (所有内置信号使用这个)或者 Signal.send_robust()。你必须提供 sender 参数(大多数情况下是一个类),还可以根据需要提供任意多个其他关键字参数。

例如,发送 pizza_done 信号可能看起来如下:

class PizzaStore:...def send_pizza(self, toppings, size):pizza_done.send(sender=self.__class__, toppings=toppings, size=size)...

send() 和 send_robust() 都返回一个元组对列表 [(receiver, response), ... ],表示被调用的接收器函数及其响应值的列表。

send() 和 send_robust() 在处理接收器函数所引发异常的方式上有所不同。 send()  捕获接收器引起的任何异常;它只是允许错误传播。因此,并非所有的接收器都会在出现错误时被通知信号。

send_robust() 捕获从 Python的 Exception 类派生的所有错误,并确保所有接收器都收到信号通知。如果发生错误,将在引发错误的接收器的元组对中返回错误实例。

回溯出现在调用 send_robust() 时返回的错误中的 __traceback__ 属性中。

三、断开信号

Signal.disconnect(receiver=Nonesender=Nonedispatch_uid=None

要断开接收器与信号的连接,调用 Signal.disconnect()。参数已在 Signal.connect() 描述。该方法成功断开连接返回 True 否则返回 False 。

receiver 参数表明要断开的接收器。它可以是 None 如果 dispatch_uid 已经被用来标识接收器。

参考链接:

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

https://www.liujiangblog.com/course/django/170

Django模型信号——django.db.models.signals相关推荐

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

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

  2. django的信号signals详解

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

  3. python限制输入数字范围_关于python:如何限制Django模型中数字字段的最大值?

    Django具有各种可用于模型的数字字段,例如 DecimalField和PositiveIntegerField. 尽管前者可以限制为存储的小数位数和总字符数,但是有任何方法可以将其限制为仅存储特定 ...

  4. django:信号机制

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

  5. Django的信号机制详解

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

  6. django的 信号

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

  7. Django框架---- 信号

    Django中的信号及其用法 Django中提供了"信号调度",用于在框架执行操作时解耦. 一些动作发生的时候,系统会根据信号定义的函数执行相应的操作 Django中内置的sign ...

  8. django模型_Django模型

    django模型 In this tutorial, we'll get into the details of Django Models. Before we do that, let's qui ...

  9. 【Python】django模型models的外键关联使用

    [Python]django模型models的外键关联使用 Python 2.7.10,django 1.8.6 外键关联:http://www.bubuko.com/infodetail-61830 ...

最新文章

  1. 分数等级_志愿填报丨填报公办普通高中志愿,分数成绩和等级成绩均需关注
  2. python中文字符_python处理中文字符
  3. OEL上使用yum install oracle-validated 简化主机配置工作
  4. win7下注册一个com失败,权限不够
  5. java cas是原子性的么_Java 并发编程:AQS 的原子性如何保证
  6. SSH(Struts2+Hibernate+Spring)开发策略
  7. mysql+cur+0_MySQLcurdate()函数的实例详解
  8. boot druid 长时间不连接 异常_Spring Boot学习:如何使用Druid数据源
  9. 冈萨雷斯《数字图像处理》读书笔记(三)——空间滤波
  10. K8S_Google工作笔记0012---通过二进制方式_部署master组件
  11. golang 解决 TCP 粘包问题
  12. Linux 内核 cgroups 新漏洞可导致攻击者逃逸容器
  13. Eclipse SonarLint 插件 “SonarLint processing file 。。。 lombok/launch/PatchFixesHider“ 解决办法
  14. 怎样设置HTML上传控件,上传文件的大小
  15. 斗地主服务器维护中,天天斗地主游戏问题解决方法
  16. Shell 掐头去尾法
  17. 荟研新材料 毕克BYK420 水性涂料和颜料浓缩浆用液态流变助剂 抗流挂剂
  18. java发邮件(简单)
  19. duck java_编程语言中的 DUCK TYPING
  20. unity中移动部件靠近时触发动画,模型替换特效演示

热门文章

  1. Nginx转发https
  2. 运维——nginx转发gitlab
  3. 网上下载的avi格式视频,没有画面怎么办?
  4. 弘辽科技:直播行业下半场弯道超车必须知道的20个要点
  5. 夜光:计算机网络笔记(三十三)
  6. java导出excel下拉长度过长,以及多个下拉的实现方法:String literals in formulas can’t be bigger than 255 characters ASCII
  7. python爬取精美壁纸
  8. case when then end用法
  9. 【Matlab PolySpace 代码静态分析使用教程】
  10. 【智慧农业】温室集成控制系统