Django 中间件
django:
- 中间件
- csrf
- 缓存
- 信号
一 、 中间件
Django的基本生命周期:
用户发起一次请求到url,再转发给视图函数,视图函数把数据取出来再把模板拿出来,最后进行渲染返回给用户
Django带有中间件的生命周期:
中间件比作是横者的管
请求来的是后先通过中间件,再到路由匹配映射到view视图里,在view视图里的逻辑执行完了后再通过中间件返回给用户
每个中间件都必须继承这个类 MiddlewareMixin
class MiddlewareMixin(object): #中间件必须继承这个类 def __init__(self, get_response=None): self.get_response = get_response super(MiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): response = self.process_request(request) if not response: response = self.get_response(request) if hasattr(self, 'process_response'): response = self.process_response(request, response) return response
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', "md.hxl.HXL", #自己写的中间件 "md.hxl.GYC", #自己定制的中间件 ]
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class LBS(MiddlewareMixin): def process_request(self,request): print("lbs-->process_request") #return HttpResponse("403。。。") #如果在这里加上return那么将不会走到views和其他中间件,从走过的中间件的process_response返回 def process_response(self,request,response): print("lbs-->process_response") return response class HXL(MiddlewareMixin): def process_request(self,request): print("HXL-->process_request") def process_response(self,request,response): print("HXL-->process_response") return response class GYC(MiddlewareMixin): def process_request(self,request): print("gyc-->process_request") def process_response(self,request,response):#必须有三个参数 """ :param request: :param response: views返回的数据 :return: 必须返回response """ print("gyc-->process_response") return response #执行的顺序 #HXL-->process_request #gyc-->process_request #views #gyc-->process_response #HXL-->process_response #直接return的顺序 #lbs-->process_request #lbs-->process_response
如果 process_request 函数有返回值的话就不再走其他中间件,就像csrf一样。
优化版
自定制中间件需要继承的类
#!/usr/bin/env python # -*- coding:utf-8 -*- from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MyMiddlewareMixin(object):#自己写一个中间件继承的类 def __init__(self, get_response=None): self.get_response = get_response super(MyMiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): #执行当前中间件的process_request response = self.process_request(request) if not response: #执行下一个中间件的__call__ response = self.get_response(request) if hasattr(self, 'process_response'): #执行当前中间件的process_response response = self.process_response(request, response) return response class LBS(MyMiddlewareMixin): def process_request(self,request): print("lbs-->process_request") return HttpResponse("403。。。") #如果在这里加上return那么将不会走到views和其他中间件,从走过的中间件的process_response返回 def process_response(self,request,response): print("lbs-->process_response") return response class HXL(MyMiddlewareMixin): def process_request(self,request): print("HXL-->process_request") def process_response(self,request,response): print("HXL-->process_response") return response class GYC(MyMiddlewareMixin): def process_request(self,request): print("gyc-->process_request") def process_response(self,request,response):#必须有三个参数 """ :param request: :param response: views返回的数据 :return: 必须返回response """ print("gyc-->process_response") return response
process_view(self, request, views, views_args, views_kwargs):
process_exception(self, request, exception):
process_exception只对views函数有效 ,对process_vie无效
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MyMiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MyMiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): #执行当前中间件的process_request response = self.process_request(request) if not response: #执行下一个中间件的__call__ response = self.get_response(request) if hasattr(self, 'process_response'): #执行当前中间件的process_response response = self.process_response(request, response) return response class LBS(MyMiddlewareMixin): def process_request(self,request): """ 在用户请求时执行的函数,拿到请求 :param request: :return: """ print("lbs-->process_request") # return HttpResponse("403。。。") #如果在这里加上return那么将不会走到views和其他中间件,从走过的中间件的process_response返回 def process_view(self, request, views_func, views_args, views_kwargs): """ 在执行views之前调用的函数,获取路由上的参数 :param request: :param views_func:对应的就是views的视图函数 :param views_args:参数列表 :param views_kwargs:关键字参数 :return: """ print("lbs-->process_view") print(views_func, views_args, views_kwargs) def process_response(self,request,response): """ 在返回数据时执行的函数,拿到返回的数据 :param request: :param response: views返回的数据 :return: 必须返回response """ print("lbs-->process_response") return response def process_exception(self, request, exception): """ 在异常触发时执行的函数,拿到异常信息 报错以后调用的函数,如果没处理则到下一个异常函数处理,都没处理则抛异常 :param request: :param exception:异常信息 :return 如果return了就不往下走,返回值返回给用户 """ print("lbs-->process_exception",exception) class HXL(MyMiddlewareMixin): def process_request(self,request): print("HXL-->process_request") def process_view(self, request, views, views_args, views_kwargs): print("HXL-->process_view") def process_response(self,request,response): print("HXL-->process_response") return response def process_exception(self, request, exception): print("HXL-->process_exception") class GYC(MyMiddlewareMixin): def process_request(self,request): print("gyc-->process_request") def process_view(self, request, views, views_args, views_kwargs): print("gyc-->process_view") def process_response(self,request,response):#必须有三个参数 """ :param request: :param response: views返回的数据 :return: 必须返回response """ print("gyc-->process_response") return response def process_exception(self, request, exception): print("gyc-->process_exception")
process_template_response(self,request,response)
from django.shortcuts import render,HttpResponse # Create your views here. class Foo: def __init__(self,request,html): self.req=request self.html=html def render(self): return render(self.req,self.html) def test(request,nid): print("views") return Foo(request,"abc.html")
返回的对象里有render的是后执行
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse class MyMiddlewareMixin(object): def __init__(self, get_response=None): self.get_response = get_response super(MyMiddlewareMixin, self).__init__() def __call__(self, request): response = None if hasattr(self, 'process_request'): #执行当前中间件的process_request response = self.process_request(request) if not response: #执行下一个中间件的__call__ response = self.get_response(request) if hasattr(self, 'process_response'): #执行当前中间件的process_response response = self.process_response(request, response) return response class LBS(MyMiddlewareMixin): def process_request(self,request): """ 在用户请求时执行的函数,拿到请求 :param request: :return: """ print("lbs-->process_request") # return HttpResponse("403。。。") #如果在这里加上return那么将不会走到views和其他中间件,从走过的中间件的process_response返回 def process_view(self, request, views_func, views_args, views_kwargs): """ 在执行views之前调用的函数,获取路由上的参数 :param request: :param views_func:对应的就是views的视图函数 :param views_args:参数列表 :param views_kwargs:关键字参数 :return: """ print("lbs-->process_view") print(views_func, views_args, views_kwargs) def process_response(self,request,response): """ 在返回数据时执行的函数,拿到返回的数据 :param request: :param response: views返回的数据 :return: 必须返回response """ print("lbs-->process_response") return response def process_exception(self, request, exception): """ 在异常触发时执行的函数,拿到异常信息 报错以后调用的函数,如果没处理则到下一个异常函数处理,都没处理则抛异常 :param request: :param exception:异常信息 :return 如果return了就不往下走,返回值返回给用户 """ print("lbs-->process_exception",exception) def process_template_response(self,request,response): """ 返回的对象如果有render方法那么就会执行 :param request:请求信息 :param response:返回的对象 :return: """ print("lbs-->process_template_response") return response class HXL(MyMiddlewareMixin): def process_request(self,request): print("HXL-->process_request") def process_view(self, request, views, views_args, views_kwargs): print("HXL-->process_view") def process_response(self,request,response): print("HXL-->process_response") return response def process_exception(self, request, exception): print("HXL-->process_exception") def process_template_response(self,request,response): print("HXL-->process_template_response") return response class GYC(MyMiddlewareMixin): def process_request(self,request): print("gyc-->process_request") def process_view(self, request, views, views_args, views_kwargs): print("gyc-->process_view") def process_response(self,request,response):#必须有三个参数 """ :param request: :param response: views返回的数据 :return: 必须返回response """ print("gyc-->process_response") return response def process_exception(self, request, exception): print("gyc-->process_exception") def process_template_response(self,request,response): print("gyc-->process_template_response") return response
中间件中可以定义四个方法,分别是:
- process_request(self,request) #在请求到了之前就已经执行了,比如csrf,请求头的过滤
- process_view(self, request, callback, callback_args, callback_kwargs)
- process_template_response(self,request,response) #在views结束后时执行的
- process_exception(self, request, exception)
- process_response(self, request, response)