Django学习之七:Django 中间件
Posted zjiqi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django学习之七:Django 中间件相关的知识,希望对你有一定的参考价值。
目录
Django 中间件
Django中间件可看作是包裹在django处理机制的外层,Httprequest和Httpresponse都要经中间件处理,从而起到全局钩子的作用,可以达到一些目的:如过滤请求,预处理请求,响应修改等。
我理解,很多基于会话的应用系统,都可以设计中间件环节。如数据库系统。中间件可以起到全局钩子的作用。django的中间件的设计就是一种递归顺序调用,利用httprequest作为递归调用的参数,httpresponse作为递归调用的return返回。
Django提供了内置的一些中间件。思考:request对象中的user属性中的用户对象是怎么来的,就是会话中间件和认证中间件处理session_id,获取用户对象,从而将用户对象放入request对象中,再交与view中进行处理。request对象在中间件开发中起到了载体的作用,非常重要。
中间件框架,设计上就是嵌套调用,初始化一个中间件函数或者中间件对象;中间件函数的初始化通过一个外层的中间件工厂函数;中间件对象的初始化当然是**中间件类的__init__()函数**喽。这两种的初始化,工厂函数和类__init__()都需要传入一个get_response函数,这个get_response的传入是django引擎会带入的,一般是初始化后的中间件列表的下一个中间件函数,或者对象,相当于就是嵌套调用递归下去,当最后的view函数处理完后再一层一层返回response,再进行response返回的中间件过程处理。原理设计就是嵌套递归返回模型(我自己起的名字,知道想表达的意思就好):
自定义中间件 - - - 大体两种方式
中间件工厂函数方式
重点:
def simple_middleware(get_response):
# One-time configuration and initialization.
def middleware(request):
# Code to be executed for each request before
# the view (and later middleware) are called.
# 注意这里的代码是view之前还是之后,两种情景的分隔就是下面这个函数调用,这是基于递归调用设计的关键之处。
response = get_response(request)
# 下面的就是view处理过后,可以处理httpresponse对象。
# Code to be executed for each request/response after
# the view is called.
return response
return middleware # 这是django初始化时调用中间件工厂函数,返回中间件函数。
基于中间件类方式
要点:
- 导入父类from django.utils.deprecation import MiddlewareMixin
- 自定义自己的中间件类继承上条导入的父类
- 定义要中间件处理的django生命周期的环节处理函数:
- process_request(self,request)
- process_view(self, request, callback_view, callback_args, callback_kwargss)
- process_template_response(request, response)
- process_response(self, request, response)
- process_exception(self, request, response, except)
- 激活中间件,在settings中的MIDDLEWARE列表中放置中间件类或者中间件工厂函数。注意放置在列表中的位置,这个很重要,因为中间可能存在依赖关系(request和response就像就中间件之间传递个的信息的载体;如auth中间件就要放在session中间件后面)。列表中就中间件的full python path(python全路径)字符串.
- 至于中间件程序模块文件,可以放在python path的任何地方,建议和组件相关放一起。
# 基于类的方式一
from django.utils.deprecation import MiddlewareMixin
class MyMiddle01(MiddlewareMixin):
# 1. 定义中间件功能,具体处理整个django请求和响应的生命周期的哪一环节。
# 2. 主要有request请求到达环节;路由Urlconf后View处理前的view预处理环节;View处理过程中抛出异常的对该异常响应的处理环节(异常情况);正常情况下view返回的response环节;还有一个模版环节(不常用);
def process_request(self, request):
pass
def process_view(self, request, callback_view, callback_args, callback_kwargs):
callback_view(request, *callback_args, *callback_kwargs)
pass
def process_template_response(request, response):
pass
def process_response(self, request, response):
return response
def process_exception(request, except):
pass
# 基于类的方式二
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
# Code to be executed for each request/response after
# the view is called.
return response
def process_view():
pass
def process_exception():
pass
def process_template_response():
pass
将中间件移除
- 方式一:将中间件从配置中移除。
- 方式二:中间件初始化是抛出MiddlewareNotUsed异常即可,在初始化中间件函数或者对象时。
实例
权限鉴别中间件
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
import re
class RbacPermissionMiddleware(MiddlewareMixin):
"""
请求访问权限中间件
"""
def process_request(self, request):
"""
权限check
:param request:
:return:
"""
req_path = request.path_info
print(‘用户请求uri‘, req_path)
# 定义白名单url
white_list = [‘/login/‘, ‘/register/‘]
for url in white_list:
url = ‘^%s$‘ % url
if re.match(url, req_path):
return None # 如果请求权限是白名单中,那么中间件返回一个None,就会进行下一个中间件处理流。
# 从session中获取权限url列表
p_list = request.session.get(‘permissions‘)
if not p_list:
return HttpResponse(‘未获取用户权限信息,请登录!‘)
p_flag = False
for p_url in p_list:
p_url = ‘^%s$‘ % p_url
if re.match(p_url, req_path):
p_flag = True
break
if not p_flag:
return HttpResponse(‘没有访问权限!‘)
总结
- 中间件函数就类似一个view函数,参数获取request,return返回response。只不过需要递归调用下一个中间件函数。(下一个中间件函数,是中间件工厂函数通过闭包传递给中间件函数的)
- 自定义中间件有多种形式:工厂函数,中间件类。
- 中间件注册到django项目时,有顺序性。
- 中间件会影响全局性能,毕竟所有请求都会进出都需要通过中间件。
额外的request_process()等都是只能创建在基于类的中间件,因为这些都是通过类的反射方式调用的。 或者异常触发,或者urlconf触发。。。
中间件函数还提供内部额外的改变请求和响应的路由路径。如:
视图函数正常执行时:
视图函数抛出异常时:
以上是关于Django学习之七:Django 中间件的主要内容,如果未能解决你的问题,请参考以下文章