django的信号主要体现了一种观察者模式
一、观察者模式(这段代码是抄的)
class Asensor: # 创建一个观察者,当被观察者到达某种状态时,或者代码运行到某处时触发观察者
@classmethod
def update(self):
print('this is A')
class Bsensor: # 创建一个观察者,当被观察者到达某种状态时,或者代码运行到某处时触发观察者
@classmethod
def update(self):
print('this is B')
class Observer: # 被观察者
L = []
status = ''
def addsensor(self,sensor):
'''
把观察者加入L
'''
if isinstance(sensor,(list,tuple)):
for sen in sensor:
self.L.append(sen)
else:
self.L.append(sensor)
def notifyAll(self):
'''
当满足某个状态时调用的方法,使观察者运行
被观察者调用时遍历所有关联的观察者触发观察者的方法,因为观察者都有update方法,这似乎与鸭子类型有关,说明与同一个被观察者
某种状态关联的观察者之间还是有共同点的。
'''
for l in self.L:
l.update()
class Obs(Observer):
# 这里用了一个继承,可以有多个继承,创建多个被相同观察者观察的被观察者 被观察者 被观察者观察
def setstatus(self,status):
self.status = status
def onfire(self,d):
if d == 1:
self.setstatus(d)
self.notifyAll()
else:
print('it is ok')
a = Asensor
b = Bsensor
ob = Observer()
ob.addsensor([a,b])
o = Obs()
o.onfire(1)
二、Django的信号
---- 自定义的signa文件 ------- 只需要将这个文件导入Django app的__init__.py文件里就能生效
# mysignals.py
from django.dispatch import receiver
from django.core import signals
from django.db.models import signals as m_signals
def mysigna(sender,**kwargs):
print(sender)
print('http请求过来啦')
@receiver(signals.request_finished) # 使用装饰器 这个装饰器代替了connect的方法。效果相同
def mysigna1(sender,**kwargs):
print(sender)
print('http请求结束啦')
class M:
def __init__(self,**kwargs):
print('我是一个类,我也可以哦')
pass
# def __call__(self, *args, **kwargs):
# print('hahahaha')
signals.request_started.connect(mysigna)
signals.request_started.connect(M)
# signals.request_finished.connect(mysigna1)
'''
Model signals:(Model信号)
pre_init # django的modal执行其构造方法前,自动触发
post_init # django的modal执行其构造方法后,自动触发
pre_save # django的modal对象保存前,自动触发
post_save # django的modal对象保存后,自动触发
pre_delete # django的modal对象删除前,自动触发
post_delete # django的modal对象删除后,自动触发
m2m_changed (m2m指的是manytomany)
# django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
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 # 创建数据库连接时,自动触发
'''
三、signals与观察者
# 自定义一个django的信号
# mysignals.py
from django.dispatch import Signal
def mysigna2(sender,**kwargs): # 信号被出发时调用的函数 ---> 观察者
print('==========im mysigna2==========')
print('sender可以发送一个对象过来',sender)
print('接收传过来的参数',kwargs)
mysigna_test = Signal(providing_args=[]) # 创建一个信号的名称
mysigna_test.connect(mysigna2) # 将函数与mysigna_test信号绑定
# views.py
class Signa_test(): # 只是为了测试下面send方法的sender参数可以传对象
pass
class Index(View): # 被观察者
def get(self,request):
mysigna.mysigna_test.send(sender=Signa_test(),豆豆='打') # 被观察者运行到这里时触发观察者
return render(request,'djangotest/index.html',{})
#console
和上面代码结合起来打印的日志
<class 'django.core.handlers.wsgi.WSGIHandler'>
http请求过来啦
我是一个类,我也可以哦
==========im mysigna2==========
sender可以发送一个对象过来 <djangotest.views.Signa_test object at 0x10c8b8b38>
接收传过来的参数 {'signal': <django.dispatch.dispatcher.Signal object at 0x10c119ac8>, '豆豆': '打'}
==========im mysigna2==========
sender可以发送一个对象过来 <djangotest.views.Index object at 0x10c8b8b00>
接收传过来的参数 {'signal': <django.dispatch.dispatcher.Signal object at 0x10c119ac8>, 'index': 'self'}
[30/Aug/2019 17:02:43] "GET /index/ HTTP/1.1" 200 391
<class 'django.core.handlers.wsgi.WSGIHandler'>
http请求结束啦