Django执行全流程图
django 中的中间件(middleware),是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。在django项目的settings模块中,有一个MIDDLEWARE变量,其中每一个元素就是一个中间件.
什么时候用中间件,什么时候用装饰器?
- 以后想要对所有的请求做同一操作时用中间件,比如把客户所有的请求写入日志
- 只是对少量的视图函数做操作时,用装饰器。(why因为如果你有上千个函数需要此操作时你不能一个个的添加吧,太麻烦了)
中间件的作用:
1.用户请求日志记录
2.登录验证
3.权限验证
Django默认的Middleware
1 MIDDLEWARE = [ 2 'django.middleware.security.SecurityMiddleware',#安全中间件 3 'django.contrib.sessions.middleware.SessionMiddleware',#session中间件,在服务端保存用户状态 4 'django.middleware.common.CommonMiddleware',#通用中间件,根据settiongs配置文件中的APPEND_SLASH(添加末尾斜杠)和PREPEND_WWW(添加www开头)
设置执行URL重写.这是为了规范化URL,每个URL都应该有特定的含义, 5 'django.middleware.csrf.CsrfViewMiddleware',#CSRF防御中间件增加防御保护以防止跨站请求伪造攻击,通过向表单中添加隐藏表单字段以及对请求进行检查以获取争取的值 6 'django.contrib.auth.middleware.AuthenticationMiddleware',#用户认证中间件,在每个Request请求对象中添加user属性,表名了当前已登录的用户 7 'django.contrib.messages.middleware.MessageMiddleware',#消息中间件 用法:提供django中的cookie以及session框架的支持,这两个基于消息中间件实现 8 'django.middleware.clickjacking.XFrameOptionsMiddleware',#X框架操作中间件,用法:通过头部信息中增加x-Frame-OptionsLAI防止简单的点击劫持。 9 10 ]
每一个中间件都有具体的功能。
中间件中一共有四个方法 :
- process_request
- process_response
- process_view
- process_exception
process_request ,process_response
1.process_request : 当浏览器中的请求来到中间件时,按照从上到下的顺序一个个执行中间件中的 process_request 函数.
如果process_request() 没有返回值时,会继续往下走,最后到达views函数
如果process_request() 有返回值即Httpesponse时,会停止进入下一个中间件的process_request,直接返回到对应中间的process_response()中.
2.process_response: 在views处理完请求后,又会依次进入到中间件(注意这时候的进入中间件的顺序与刚来的 时候相反,看我的上图),这时候会调用process_response方法,在这里必须有返回值这个返回值就是views模块中的函数处理的结果.
用例子来说明这个流程:
views.py
from django.shortcuts import render,HttpResponse # Create your views here. def index(request): print("view函数") return HttpResponse("你好,中国")
middleswares.py
class MD1(MiddlewareMixin): def process_request(self,request): print("MD1请求",request) def process_response(self,request,response): print("MD1响应",) return response class MD2(MiddlewareMixin): def process_request(self, request): print("MD2请求") def process_response(self, request, response): #注意这里要接收三个参数 print("MD2响应",request) print("MD2响应",response) return response
settings.py
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'middlewares.middleswares.MD1', 'middlewares.middleswares.MD2' ]
结果:
MD1请求 <WSGIRequest: GET '/index/'> MD2请求 view函数 MD2响应 <WSGIRequest: GET '/index/'> MD2响应 <HttpResponse status_code=200, "text/html; charset=utf-8"> #text/html的意思是将文件的content-type设置为text/html的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。 MD1响应
如果把middleswares.py这样改动
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse class MD1(MiddlewareMixin): def process_request(self,request): print("MD1请求",request) return HttpResponse("你好") ####把这里改动了 def process_response(self,request,response): print("MD1响应",response) return response class MD2(MiddlewareMixin): def process_request(self, request): print("MD2请求") def process_response(self, request, response): print("MD2响应",request) print("MD2响应",response) return response
py的结果:
MD1请求 <WSGIRequest: GET '/index/'> MD1响应 <HttpResponse status_code=200, "text/html; charset=utf-8">
前端页面结果:
自定义中间件
如何我们自己写一个中间件呢? 我们现在建立一个session版的登录验证的中间件
1.建立一个文件夹,里边包含中间件模块
2.在模块中写
middletext.py
from django.shortcuts import render,redirect,HttpResponse
from django.utils.deprecation import MiddlewareMixin #导入这个类
class M1(MiddlewareMixin): #继承MiddlewareMixxin这个类
def process_request(self,request):
ret=request.session.get("user",None)
print("ret",ret)
if request.path_info=="/login/": #设立白名单否则会出现重定向,死循环
return None #这样会继续向下走
else:
if not ret:
return redirect("/login/")
def process_response(self,request,response):
print("结束")
return response #没有return response 得不到views执行的值
3.在settings中的middleware 中配置中间件
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', "middletext.middletext.M1" #这个就是你配置的中间件 ]
4. 在views中写入函数
def login(request): if request.method=="POST": username=request.POST.get("username") password=request.POST.get('password') if username=="alex" and password=="123456": print("Nihoa ") request.session["user"]=username return HttpResponse("登录成功") else: ret="密码错误" print(ret) render(request,"loggin.html",{"ret":ret}) return render(request,"loggin.html") def index(request): print("index") return render(request,"index.html") def home(request): return render(request,"home.html")
5.配置url 这样就可以了
process_view
当最后一个中间的process_request到达路由关系映射之后,拿到 视图函数的名称、参数(注意不执行),然后进入到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户。应用:在django的csrf验证的中间件中,把验证token的这步放在了,process_view中
process_view(self, request, callback, callback_args, callback_kwargs)
Mymiddleswares.py修改如下
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse class MD1(MiddlewareMixin): def process_request(self,request): print("MD1请求",request) def process_response(self,request,response): print("MD1响应",response) return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md1view") class MD2(MiddlewareMixin): def process_request(self, request): print("MD2请求") def process_response(self, request, response): print("MD2响应",request) print("MD2响应",response) return response
结果:
MD1请求 <WSGIRequest: GET '/index/'> MD2请求 Md1view view函数 MD2响应 <WSGIRequest: GET '/index/'> MD2响应 <HttpResponse status_code=200, "text/html; charset=utf-8"> MD1响应 <HttpResponse status_code=200, "text/html; charset=utf-8">
所以如果任何一个 process_view()
返回了HttpResponse对象,那么在它后面process_view()
将会被省略,不会被执行,直接跳到process_response(),函数倒着执行
范例:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse class MD1(MiddlewareMixin): def process_request(self,request): print("MD1请求",request) def process_response(self,request,response): print("MD1响应",response) return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md1view") return HttpResponse("你好") class MD2(MiddlewareMixin): def process_request(self, request): print("MD2请求") def process_response(self, request, response): print("MD2响应",request) print("MD2响应",response) return response
def process_view(self, request, callback, callback_args, callback_kwargs):
print("Md2view")
py结果:
MD1请求 <WSGIRequest: GET '/index/'> MD2请求 Md1view MD2响应 <WSGIRequest: GET '/index/'> MD2响应 <HttpResponse status_code=200, "text/html; charset=utf-8"> MD1响应 <HttpResponse status_code=200, "text/html; charset=utf-8">
前端页面
process_view可以用来调用视图函数:
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse class MD1(MiddlewareMixin): def process_request(self,request): print("MD1请求",request) def process_response(self,request,response): print("MD1响应",response) return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md1view") response = callback(request, *callback_args, **callback_kwargs) return response class MD2(MiddlewareMixin): def process_request(self, request): print("MD2请求") def process_response(self, request, response): print("MD2响应",request) print("MD2响应",response) return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md2view")
py.结果
MD1请求 <WSGIRequest: GET '/index/'> MD2请求 Md1view views.py中的函数 MD2响应 <WSGIRequest: GET '/index/'> MD2响应 <HttpResponse status_code=200, "text/html; charset=utf-8"> MD1响应 <HttpResponse status_code=200, "text/html; charset=utf-8">
前端:
process_exception
当视图函数出现错误时,会走process_exception函数,并且倒着走process_exception函数,可以在这个函数中返回一个对象,服务器不至于崩溃
process_exception(
self
, request, exception)
middleware.py
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render,HttpResponse class MD1(MiddlewareMixin): def process_request(self,request): print("MD1请求",request) def process_response(self,request,response): print("MD1响应",response) return response def process_view(self, request, callback, callback_args, callback_kwargs): print("Md1view") def process_exception(self, request, exception): print("md1 process_exception...") return HttpResponse("error")
views.py
def index(request): print("views.py中的函数") name return HttpResponse("你好,中国")
py页面:
MD1请求 <WSGIRequest: GET '/index/'> MD2请求 Md1view Md2view views.py中的函数 md2 process_exception... md1 process_exception... MD2响应 <HttpResponse status_code=200, "text/html; charset=utf-8"> MD1响应 <HttpResponse status_code=200, "text/html; charset=utf-8">
前端页面
流程图: