信号:框架内部已帮助开发者预留的可扩展的位置
一、Django 的信号
项目目录结构:
django_signal
|--- app01
|--- models.py
|--- views.py
...
|--- django_signal
|--- __init__.py
|--- urls.py
...
|--- manage.py
django_signal/django_signal/urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^func1/', views.func1),
url(r'^func2/', views.func2),
url(r'^func3/', views.func3),
url(r'^func4/', views.func4),
]
django_signal/django_signal/__init__.py
# 程序刚启动起来的时候,该py文件会先执行,所以信号写在了该文件中 from django.db.models import signals def before_save1(*args,**kwargs): # 发送的信号的内容(signals.pre_save 的)
print('有车来了,我要服务了--》',args,kwargs) def before_save2(*args,**kwargs):
print('有车来了,我要服务了--》',args,kwargs) def after_save1(*args,**kwargs):
print('有车来了,完事了--》',args,kwargs) signals.pre_save.connect(before_save1) # signals.pre_save : 数据库ORM 保存之前 的信号; .connect() 中放函数(如数据库增加之前想要做的操作); 这行代码的含义:把 before_save1 这个函数注册到了 signals.pre_save 这个信号中
signals.pre_save.connect(before_save2) # 也是数据库保存之前的信号:数据库增加和更新之前会执行(内部用 .save()来触发的) signals.post_save.connect(after_save1) # 数据库保存之后进行的操作的信号 """
Django 的内置信号:
Model signals
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 # 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 # 创建数据库连接时,自动触发
"""
django_signal/app01/modles.py
from django.db import models class User(models.Model): title = models.CharField(max_length=32)
django_signal/app01/views.py
from django.shortcuts import render,HttpResponse
from app01 import models def func1(request):
# 该视图没有数据库修改的操作,所以请求通过该视图时不会触发 信号
return HttpResponse('创建成功') def func2(request):
models.User.objects.create(title='小男孩')
return HttpResponse('创建成功') def func3(request):
models.User.objects.create(title='小少年')
return HttpResponse('创建成功') def func4(request):
models.User.objects.create(title='小青年')
return HttpResponse('创建成功')
二、Flask 的信号
1. 安装第三方组件:blinker
pip install blinker
示例代码:
from flask import Flask,render_template
from flask import signals app = Flask(__name__) def x1(arg):
print('x1')
def x2(arg):
print('x2')
signals.request_started.connect(x1) # signals.request_started : 请求刚开始时触发的信号
signals.request_started.connect(x2) @app.before_request
def bf():
print('bbbbb')
return render_template("asdfadf") @app.route('/index')
def func():
print('视图函数')
return "asdfasdf" if __name__ == '__main__':
# app.__call__
app.run()
# with app.app_context():
# pass """
Flask 的内置信号:
request_started = _signals.signal('request-started') # 请求到来前执行
request_finished = _signals.signal('request-finished') # 请求结束后执行 before_render_template = _signals.signal('before-render-template') # 模板渲染前执行
template_rendered = _signals.signal('template-rendered') # 模板渲染后执行 got_request_exception = _signals.signal('got-request-exception') # 请求执行出现异常时执行 request_tearing_down = _signals.signal('request-tearing-down') # 请求执行完毕后自动执行(无论成功与否)
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')# 应用上下文执行完毕后自动执行(无论成功与否) appcontext_pushed = _signals.signal('appcontext-pushed') # 应用上下文push时执行
appcontext_popped = _signals.signal('appcontext-popped') # 应用上下文pop时执行
message_flashed = _signals.signal('message-flashed') # 调用flask在其中添加数据时,自动触发
""" # 由于Flask本身没有ORM,所以Flask没有数据库相关的信号;它只有一些Flask内置的信号,如 请求走到哪儿时的信号 """
signals.request_started 的信号 在 before_request 这个装饰器 之前执行;
被 before_request 装饰的函数可以有返回值,并且能够拦截请求;但信号拦截不了请求,请求只能穿过信号(信号的返回值不影响请求的流程)
"""