一、什么是中间件
官方的说法:
中间件是一个介入Django的请求和响应的处理过程中的钩子框架。它是一个轻量级,底层的“插件”系统,用于在全局修改Django的输入或输出。
通俗理解:
django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件。
二、激活中间件
要激活一个中间件组件,需要把它添加到你Django配置文件中的MIDDLEWARE_CLASSES 列表中。
在django生成项目之后,在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',
]
默认激活的中间件往往不是必须的,但是有的中间件是相互依赖的,所以,一旦项目生成之后,默认激活的中间件最好不要更改。
三、钩子和应用顺序
在一个中间件中最多可以定义几个函数,答案是5个,因为中间件本质上是一个类,因此可以说一个中间件中最多可以定义5个方法。分别是
- process_request
- process_view
- process_response
- process_exception
- process_render_template
上面说中间件像是一个钩子框架,那么这些钩子的处理顺序是怎么样呢?
在请求阶段中,调用视图之前,Django会按照MIDDLEWARE_CLASSES中定义的顺序自顶向下应用中间件。会用到两个钩子:
- process_request()
- process_view()
在响应阶段中,调用视图之后,中间件会按照相反的顺序应用,自底向上。会用到三个钩子:
- process_exception() (仅当视图抛出异常的时候)
- process_template_response() (仅用于模板响应)
- process_response()
像这样
大致流程:
1 request请求先逐个经过中间件的process_request()方法到达路由系统
2 到达路由系统之后在返回第一个中间件,在逐个进入中间件的process_view()进入视图函数
3 进入视图函数之后返回,再经过最后一个中间件到第一个中间件的process_response()方法。
这是正常的流程,但是如果出现异常呢?
- 当在视图函数中出现异常之后,再经过最后一个中间件到第一个中间件的process_exception()方法
- 如果返回的有render方法,则调用process_template_response(),经过最后一个中间件到第一个中间件
四、中间件做什么
- 权限
- 用户登录验证
- django的csrf原理
拓展:
1 csrf防范怎么实现:中间件'django.middleware.csrf.CsrfViewMiddleware', it works!
2 这个中间件实在什么时候起作用,或者说是内部的哪个钩子起作用,process_view()
原因也很简单,虽然process_request()
的作用时间更早,但是如果想判断一个试图函数是否需要做csrf认证,就需要检查这个视图是否别装饰
1、在FBV中
情况一、
from django.views.decorators.csrf import csrf_protect # 去掉中间件,当前视图需要认证
@csrf_protect
def users(request):
pass
情况二、
from django.views.decorators.csrf import csrf_exempt # 保留中间件,当前视图无需认证
@csrf_exempt
def users(request):
pass
2、在CBV中
在CBV中直接装饰get, post等方法无效的
方式一:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
class StudentsView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(StudentsView,self).dispatch(request, *args, **kwargs)
def get(self,request,*args,**kwargs):
print('get方法')
return HttpResponse('GET')
def post(self, request, *args, **kwargs):
return HttpResponse('POST')
def put(self, request, *args, **kwargs):
return HttpResponse('PUT')
def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE')
在CBV模式中,请求都要经过View中的dispatch反射执行,所以这里继承父类中dispatch方法增加装饰
方式二:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
@method_decorator(csrf_exempt,name='dispatch')
class StudentsView(View):
def get(self,request,*args,**kwargs):
print('get方法')
return HttpResponse('GET')
def post(self, request, *args, **kwargs):
return HttpResponse('POST')
def put(self, request, *args, **kwargs):
return HttpResponse('PUT')
def delete(self, request, *args, **kwargs):
return HttpResponse('DELETE')
五、自定义中间件
也可以编写自己的中间件。每个中间件组件是一个单独的Python的class,可以定一个或多个上面的方法。
注意事项
- 中间件的类不能是任何类的子类。
- 中间件可以存在与你Python路径中的任何位置。 Django所关心的只是被包含在MIDDLEWARE_CLASSES中的配置。通常放在项目目录下
1、中间件存放位置
例如 # 存放中间件的文件夹与manage.py 在同一父目录下
djangoproject
- middle
- customize_middleware.py # 自定义中间件
- manage.py
2、中间件内部
class RequestExeute(object):
def process_request(self,request):
pass
def process_view(self, request, callback, callback_args, callback_kwargs):
pass
def process_exception(self, request, exception):
pass
def process_response(self, request, response):
pass
3、激活中间件
在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',
'middle.customize_middleware.RequestExeute', # 自定义中间件
]