Django之resquest进入中间件《一》
时间:2020-05-21
本文章向大家介绍Django之resquest进入中间件《一》,主要包括Django之resquest进入中间件《一》使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
class WSGIHandler(base.BaseHandler): request_class = WSGIRequest def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)
#在wsgihandler生成实例时,在__init__魔方方法里面就进行了加载中间件 self.load_middleware() def __call__(self, environ, start_response): set_script_prefix(get_script_name(environ)) signals.request_started.send(sender=self.__class__, environ=environ)
#封装成request对象 request = self.request_class(environ) response = self.get_response(request) response._handler_class = self.__class__ status = '%d %s' % (response.status_code, response.reason_phrase) response_headers = [ *response.items(), *(('Set-Cookie', c.output(header='')) for c in response.cookies.values()), ] start_response(status, response_headers) if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'): # If `wsgi.file_wrapper` is used the WSGI server does not call # .close on the response, but on the file wrapper. Patch it to use # response.close instead which takes care of closing all files. response.file_to_stream.close = response.close response = environ['wsgi.file_wrapper'](response.file_to_stream, response.block_size) return response
load_middleware函数:
def load_middleware(self): """ Populate middleware lists from settings.MIDDLEWARE. Must be called after the environment is fixed (see __call__ in subclasses). """ self._view_middleware = [] self._template_response_middleware = [] self._exception_middleware = []
# 封装 这个时候就已经把slef._get_response函数绑定到了装饰器的inner函数上面 handler = convert_exception_to_response(self._get_response) for middleware_path in reversed(settings.MIDDLEWARE): middleware = import_string(middleware_path) try:
"""遍历中间件,通过下面的黄色标记并在中间件类上层层包裹上一级中间件,通过类的__call__魔方方法达到动态添加装饰器的效果,
每个中间件中的process_request方法对进来的request进行合法检验""" mw_instance = middleware(handler) except MiddlewareNotUsed as exc: if settings.DEBUG: if str(exc): logger.debug('MiddlewareNotUsed(%r): %s', middleware_path, exc) else: logger.debug('MiddlewareNotUsed: %r', middleware_path) continue if mw_instance is None: raise ImproperlyConfigured( 'Middleware factory %s returned None.' % middleware_path )
#在加载中间件时,将核心对view,response进行检验的钩子函数添加到列表中,为下一步检验做准备 if hasattr(mw_instance, 'process_view'): self._view_middleware.insert(0, mw_instance.process_view) if hasattr(mw_instance, 'process_template_response'): self._template_response_middleware.append(mw_instance.process_template_response) if hasattr(mw_instance, 'process_exception'): self._exception_middleware.append(mw_instance.process_exception) handler = convert_exception_to_response(mw_instance) # We only assign to this when initialization is complete as it is used # as a flag for initialization being complete. self._middleware_chain = handler
进入get_response()函数
def get_response(self, request): """Return an HttpResponse object for the given HttpRequest.""" # Setup default url resolver for this thread set_urlconf(settings.ROOT_URLCONF)
#根据程序上下文 找到 slef._middleware_chain = handler= convert_exception_to_response(middlerinstance)
而且这个handler 是一个装饰器
response = self._middleware_chain(request) response._resource_closers.append(request.close) if response.status_code >= 400: log_response( '%s: %s', response.reason_phrase, request.path, response=response, request=request, ) return response
当运行self._middleware_chain(request),会先进行上述我们添加的中间件类中的process_request方法对request中的首部关键字进行合法性检验,然后调用核心函数self._get_response():
ps:这与我们在setting中定义的middleware是一致顺序,因为在加载的时候用的reverse函数,和多层装饰器执行顺序一样,是一个后进先出的栈的效果:
总结就是:serverhandler实例化时,就会加载中间件,将核心函数self._get_response()AOP修饰各种中间件函数保存到列表里面为下一步认证做准备,然后通过中间件类的回调方法实现动态添加各种中间件类的process_request方法装饰核心函数-------成为一个多层装饰器。
所以当调用get_response时,会先进行一些列的process_request认证,然后才开始执行核心函数self._get_response()
原文地址:https://www.cnblogs.com/zengmu/p/12932459.html
- asp.net webform中submit按钮使用不当很容易犯的一个错误
- 使用代码为textview设置drawableLeft
- 使用 ASP.NET Web API 构建超媒体 Web API
- Robert Xiao:下一个触点在哪里?
- 使用脚本操作UpdatePanel中控件的问题
- Gerrit上分支操作记录(创建分支、删除分支)
- flash 显示 qq客服状态
- android获得ImageView图片的等级
- SqlServer:此数据库处于单用户模式,导致数据库无法删除的处理
- jQuery中排除指定元素,同时选择剩下的所有元素
- windows客户机连接gerrit的一个报错处理
- 装箱与值类型虽然很容易理解,但是在实际使用中,并不总是能100%用对
- Jexus 配置ssl
- 局部打印插件 jquery.PrintArea.js
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 分布式存储Ceph之PG状态详解
- JS中的事件循环机制与宏队列、微队列笔记
- Redis 哨兵机制以及底层原理深入解析,这次终于搞清楚了
- SQL 找出分组中具有极值的行
- 接入层Nginx架构及模块介绍分享
- 【问题修复】mds0: Metadata damage detected
- 【服务网格架构】Envoy架构概览(6):异常检测
- 分布式存储Cephfs读取优化方案
- SQL 确定序列里缺失值的范围
- 【问题修复】osd自杀问题跟踪
- mds元信息缓存不释放问题
- 线程安全问题,synchronized 和 ReentrantLock 详细讲解
- Ceph RBD灾备方案对比
- RBD快照灾备方案
- 从条件运算符说起,反思什么是好代码