文章目录
Django组件
中间件
中间件的概念
中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。
如果你想修改请求,例如被传送到view中的HttpRequest对象。 或者你想修改view返回的HttpResponse对象,这些都可以通过中间件来实现。
可能你还想在view执行之前做一些操作,这种情况就可以用 middleware来实现。
Django默认的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',
]
自定制中间件
-
中间件可以定义五个方法,分别是:
-
process_request(self,request)
-
process_view(self, request, view_func, view_args, view_kwargs)
-
process_exception(self, request, exception)
-
process_response(self, request, response)
-
process_template_response(self,request,response)
(了解)
自定制中间件使用步骤:
-
在APP下面新建一个py文件(文件名称自定制)
middlewares.py
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): pass # 默认没有返回值, 如果有返回值,会终止后面的中间件的执行,并且会直接返回当前类下的process_response方法. def process_response(self, request, response): return response
-
在
settings.py
注册MIDDLEWAREMIDDLEWARE = [ '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', 'app01.middlewares.MD1', # 自定义中间件MD1 'app01.middlewares.MD2', # 自定义中间件MD2 ]
执行顺序:
中间件可以定义的方法:
process_request方法
process_request(self, request)
在视图之前执行
按照settings的注册顺序执行
默认没有返回值.
有返回值时,直接执行该类下的process_response
方法返回.后面还有中间件,就不会执行.
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
我们访问一个视图,会发现终端中打印如下内容:
MD1里面的 process_request
MD2里面的 process_request
app01 中的 index视图
process_response方法
process_response(self, request, response)
在视图之后执行
按照settings的注册倒序执行
必须要有返回值,没有会报错(http基于请求响应模式)
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
访问一个视图,看一下终端的输出:
MD1里面的 process_request
MD2里面的 process_request
app01 中的 index视图
MD2里面的 process_response
MD1里面的 process_response
process_view方法
process_view(self, request, view_func, view_args, view_kwargs)
在视图之前执行
按照settings的注册顺序执行
默认没有返回值.
有返回值时,直接执行该类下的process_response
方法返回.后面还有中间件,就不会执行.
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD1 中的process_view")
print(view_func, view_func.__name__)
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD2 中的process_view")
print(view_func, view_func.__name__)
访问index视图函数,看一下输出结果:
MD1里面的 process_request
MD2里面的 process_request
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x000001DE68317488> index
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x000001DE68317488> index
app01 中的 index视图
MD2里面的 process_response
MD1里面的 process_response
process_exception方法
process_exception(self, request, exception)
在视图之后执行,触发条件为:视图内部触发异常,才能执行.
按照settings的注册倒序执行
当有返回值时,如果是HttpResponse对象,Django将调用模板和中间件中的process_response
方法,并返回给浏览器,,页面不会报错(返回状态码为200
, 反之 500
)
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD1 中的process_view")
print(view_func, view_func.__name__)
def process_exception(self, request, exception):
print(exception)
print("MD1 中的process_exception")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD2 中的process_view")
print(view_func, view_func.__name__)
def process_exception(self, request, exception):
print(exception)
print("MD2 中的process_exception")
- 如果视图函数中无异常,process_exception方法不执行。
想办法,在视图函数中抛出一个异常:
def index(request):
print("app01 中的 index视图")
raise ValueError("呵呵")
return HttpResponse("O98K")
- 在MD2的
process_exception
中返回一个响应对象
def process_exception(self, request, exception):
print(exception)
print("MD2 中的process_exception")
return HttpResponse(str(exception)) # 返回一个响应对象
- 看输出结果:
MD1里面的 process_request
MD2里面的 process_request
--------------------------------------------------------------------------------
MD1 中的process_view
<function index at 0x0000022C09727488> index
--------------------------------------------------------------------------------
MD2 中的process_view
<function index at 0x0000022C09727488> index
app01 中的 index视图
呵呵
MD2 中的process_exception
MD2里面的 process_response
MD1里面的 process_response
session源码解析
- 第一步在process_reqeust方法
- 第二步在视图层
- 第三步在process_response方法
详细步骤:
1.
4.
5.
6.
7.
8.process_reqeust方法
9.
10.视图设置session
request.session['is_login'] = True
11.process_response 方法
12.
13.
14.
15.
16.
17.
18.
19.
request.session.flush()的流程
截图:
1.
2.
3.
4.