Django之resquest进入中间件《一》

Posted zengmu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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进行合法检验; process_response对核心函数self._get_response执行后返回的response进行验证"""
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()

以上是关于Django之resquest进入中间件《一》的主要内容,如果未能解决你的问题,请参考以下文章

Django之中间件

爬虫之Resquests模块的使用

django之设置中间件模板

在 django 中间件中使用 HTTP HttpResponsePermanentRedirect 时站点进入重定向循环

Django之中间件

Django之中间件