码农行者 码农行者
首页
  • Python

    • 语言特性
    • Django相关
    • Tornado
    • Celery
  • Golang

    • golang学习笔记
    • 对比python学习go
    • 模块学习
  • JavaScript

    • Javascript
  • 数据结构预算法笔记
  • ATS
  • Mongodb
  • Git
云原生
运维
垃圾佬的快乐
  • 数据库
  • 机器学习
  • 杂谈
  • 面试
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

DeanWu

软件工程师
首页
  • Python

    • 语言特性
    • Django相关
    • Tornado
    • Celery
  • Golang

    • golang学习笔记
    • 对比python学习go
    • 模块学习
  • JavaScript

    • Javascript
  • 数据结构预算法笔记
  • ATS
  • Mongodb
  • Git
云原生
运维
垃圾佬的快乐
  • 数据库
  • 机器学习
  • 杂谈
  • 面试
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Python

    • 语言特性

    • Django

      • Django 简单入门及最佳实践
      • Django学习笔记-url、视图
      • Django学习笔记-模型(1)模型的定义
      • Django学习笔记-模型(2)模型的操作
      • Django学习笔记-模板
      • Django 文章整理- 学习路径总结
      • Django 3.0 异步试用分享
      • Django 3.2 新功能尝鲜
      • Django admin 定制案例
      • Django 三个异步使用的案例
      • Django学习笔记- Class View
      • django 相关命令总结
      • django form表单的数据 select 值更新问题
      • Django自定义管理器(objects)后遇到的问题
      • django signal 使用总结
        • 什么是django的signal
        • 最佳使用场景
          • 通知类
          • 初始化类
          • 其他一些使用场景总结
        • 如何使用
          • 内建signal的使用
          • 第一步,编写receiver并绑定到signal
          • 第二步,加载signal
          • 自定义signal的使用
          • 第一步, 编写signal
          • 第二步,加载signal
          • 第三步,事件触发时,发送signal
          • 第四步,收到signal,执行receiver
        • 总结
        • 参考
      • 单文件 Django 服务构建
      • 使用 supervisor 来监控 django celery
      • Django 中如何使用 sass
      • Django uwsgi 启动问题 unavailable modifier requested 0
      • Django uwsgi 启动问题 ImportError No module named os
    • Best.Practices.for.Django

    • Djangorestfulframework

    • Celery

    • Tornado

    • Flask

    • FastApi

    • virtualenv

  • Golang

  • Javascript

  • 开发语言
  • Python
  • Django
DeanWu
2017-01-24
目录

django signal 使用总结

最近在已经开发好的项目上加功能,想到了django的signal,整理记录如下备查。

# 什么是django的signal

官方文档描述如下:

Django includes a “signal dispatcher” which helps allow decoupled applications get notified when actions occur elsewhere in the framework.In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.

Django内部包含了一位“信号调度员”:当某事件在框架内发生时,它可以通知到我们的应用程序。 简而言之,当event(事件)发生时,signals(信号)允许若干 senders(寄件人)通知一组 receivers(接收者)。这在我们多个独立的应用代码对同一事件的发生都感兴趣时,特别有用。

个人理解,django的signal可理解为django内部的钩子,当一个事件发生时,其他程序可对其作出相关反应,可通过signal来回调定义好的处理函数(receivers),从而更大程度的解耦我们的系统。

# 最佳使用场景

# 通知类

通知是signal最常用的场景之一。例如,在论坛中,在帖子得到回复时,通知楼主。从技术上来讲,我们可以将通知逻辑放在回复保存时,但是这并不是一个好的处理方式,这样会时程序耦合度增大,不利于系统的后期扩展维护。如果我们在回复保存时,只发一个简单的信号,外部的通知逻辑拿到信号后,再发送通知,这样回复的逻辑和通知的逻辑做到了分开,后期维护扩展都比较容易。

# 初始化类

信号的另一个列子便是事件完成后,做一系列的初始化工作。

# 其他一些使用场景总结

以下情况不要使用signal:

  • signal与一个model紧密相关, 并能移到该model的save()时
  • signal能使用model manager代替时
  • signal与一个view紧密相关, 并能移到该view中时

以下情况可以使用signal:

  • signal的receiver需要同时修改对多个model时
  • 将多个app的相同signal引到同一receiver中处理时
  • 在某一model保存之后将cache清除时
  • 无法使用其他方法, 但需要一个被调函数来处理某些问题时

# 如何使用

django 的 signal 使用可分为2个模块:

  • signal :signal定义及触发事件
  • receiver : signal 接受函数

# 内建signal的使用

django 内部有些定义好的signal供我们使用:

模型相关:

  • pre_save 对象save前触发
  • post_save 对象save后触发
  • pre_delete 对象delete前触发
  • post_delete 对象delete后触发
  • m2m_changed ManyToManyField 字段更新后触发

请求相关:

  • request_started 一个request请求前触发
  • request_finished request请求后触发

针对django自带的signal,我们只需要编写receiver 即可,使用如下。

# 第一步,编写receiver并绑定到signal

myapp/signals/handlers.py

from django.dispatch import receiver
from django.core.signals import request_finished
 
## decorators 方式绑定
@receiver(request_finished, dispatch_uid="request_finished")
def my_signal_handler(sender, **kwargs):
    print("Request finished!================================")

# 普通绑定方式
def my_signal_handler(sender, **kwargs):
    print("Request finished!================================")

request_finished.connect(my_signal_handler)

#####################################################
# 针对model 的signal 
from django.dispatch import receiver
from django.db.models.signals import post_save
 
from polls.models import MyModel
 
 
@receiver(post_save, sender=MyModel, dispatch_uid="mymodel_post_save")
def my_model_handler(sender, **kwargs):
 print('Saved: {}'.format(kwargs['instance'].__dict__))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  • dispatch_uid 确保此receiver 只调用一次

# 第二步,加载signal

myapp/__init__py

default_app_config = 'myapp.apps.MySendingAppConfig'
1

myapp/apps.py

from django.apps import AppConfig
 
 
class MyAppConfig(AppConfig):
    name = 'myapp'
 
    def ready(self):
        # signals are imported, so that they are defined and can be used
        import myapp.signals.handlers
1
2
3
4
5
6
7
8
9

到此,当系统受到request 请求完成后,便会执行receiver。

其他内建的signal,参考官方文档: https://docs.djangoproject.com/en/1.9/topics/signals/ (opens new window)

# 自定义signal的使用

自定义signal,需要我们编写 signal和 receiver 。

# 第一步, 编写signal

myapp.signals.signals.py

import django.dispatch
 
my_signal = django.dispatch.Signal(providing_args=["my_signal_arg1", "my_signal_arg_2"])
1
2
3

# 第二步,加载signal

myapp/__init__py

	
default_app_config = 'myapp.apps.MySendingAppConfig'
1
2

myapp/apps.py

from django.apps import AppConfig
 
 
class MyAppConfig(AppConfig):
    name = 'myapp'
 
    def ready(self):
        # signals are imported, so that they are defined and can be used
        import myapp.signals.handlers
1
2
3
4
5
6
7
8
9

# 第三步,事件触发时,发送signal

myapp/views.py

from .signals.signals import my_signal
 
my_signal.send(sender="some function or class",
               my_signal_arg1="something", my_signal_arg_2="something else"])
1
2
3
4

自定义的signal,django已经为我们编写了此处的事件监听。

# 第四步,收到signal,执行receiver

myapp/signals/handlers.py

from django.dispatch import receiver
from myapp.signals.signals import my_signal
 
 
@receiver(my_signal, dispatch_uid="my_signal_receiver")
def my_signal_handler(sender, **kwargs):
    print('my_signal received')

1
2
3
4
5
6
7
8

此时,我们自定义的signal 便开发完成了。

# 总结

  • django signal 的处理是同步的,勿用于处理大批量任务。
  • django signal 对程序的解耦、代码的复用及维护性有很大的帮助。

以上为个人观点,如有疑问欢迎交流。

# 参考

http://sabinemaennel.ch/django/signals-in-django/ (opens new window) https://docs.djangoproject.com/en/1.10/topics/signals/ (opens new window) http://www.weiguda.com/blog/38/ (opens new window) http://www.python88.com/topic/151 (opens new window)

#Django#Django-signal
上次更新: 2023/03/28, 16:27:19
Django自定义管理器(objects)后遇到的问题
单文件 Django 服务构建

← Django自定义管理器(objects)后遇到的问题 单文件 Django 服务构建→

最近更新
01
chromebox/chromebook 刷bios步骤
03-01
02
redis 集群介绍
11-28
03
go语法题二
10-09
更多文章>
Theme by Vdoing | Copyright © 2015-2024 DeanWu | 遵循CC 4.0 BY-SA版权协议
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式