【Django】源码解析django启动和访问过程(四)

Django访问过程(二)

Django访问过程(一)中我们了解到请求内容进入了django.core.handlers.wsgi.WSGIHandler.__call__进行处理,下面我们接着个方法继续解读源码。

django.core.handlers.wsgi.WSGIHandler.call

class WSGIHandler(base.BaseHandler):
    request_class = WSGIRequest

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # django服务启动阶段已经实例化中间件并加载了中间件的相关方法。
        self.load_middleware()

    def __call__(self, environ, start_response):
    	# 开辟线程变量
        set_script_prefix(get_script_name(environ))
        # 发送一个requet处理信号
        # 前面我们提到runserver命令模块,命令继承了‘django.core.management.base.BaseCommand’类,
        # 而BaseCommand中执行了'from django.db import DEFAULT_DB_ALIAS, connections'导入模块操作,
        # 在db.__init__.py中建立了request_started信号连接。
        '''
        # 建立信号连接,传递reset_queries作为处理信号的方法
        signals.request_started.connect(reset_queries)
        # 建立信号连接,传递close_old_connections作为处理信号的方法
        signals.request_started.connect(close_old_connections)
        # 建立信号连接,传递close_old_connections作为处理信号的方法
		signals.request_finished.connect(close_old_connections)
        '''
        signals.request_started.send(sender=self.__class__, environ=environ)
        # 用WSGIRequest封装request,这里就是我们视图中用到的request的来源。
        request = self.request_class(environ)
        # 设置路由
        # 将request交给中间件处理
       	# 这里得到了经过中间件和视图处理过的response 
        response = self.get_response(request)
        # 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)
	        # 根据装饰器闭包原理去调用中间件的__call__方法
	        # 注意中间件的实例化过程是中间件表从下往上
	        response = self._middleware_chain(request)
	        response._closable_objects.append(request)
	        if response.status_code >= 400:
	            log_response(
	                '%s: %s', response.reason_phrase, request.path,
	                response=response,
	                request=request,
	            )
	        return response
		'''
      	# 中间件处理过程如下:
       	'''
		class MiddlewareMixin:
		    def __init__(self, get_response=None):
		    	# 启动时候load_middleware()对中间件进行实例化,
		    	# 传入了django.core.handlers.base.BaseHandler._get_response
		        self.get_response = get_response
		        super().__init__()
		
		    def __call__(self, request):
		        response = None
		        if hasattr(self, 'process_request'):
		        	# 交给中间件的process_request方法处理,按中间件列表从上到下执行
		        	# 对request进行进一步加工
		        	# 一般情况下没有返回值或者返回响应错误的response
		            response = self.process_request(request)
		        # 继续将requets交给django.core.handlers.base.BaseHandler._get_response处理
		        # 先根据路由配置得到路由表,
		        # 然后根据请求地址信息从路由表找到视图函数,视图函数的参数
		        # 接着将requset、视图函数和视图函数参数交给了中间件的process_view处理,按中间件列表从上到下执行
		        # 如果视图处理过后得到的response有render方法,
		        # 接着将response交给中间件的process_template_response方法处理,按中间件列表从下往上执行;
		        # 这里必须得到response结果,否则调用中间件的process_exception方法进行异常处理,按中间件列表从下往上执行。
		        response = response or self.get_response(request)
		        if hasattr(self, 'process_response'):
		        	# 将的到的request和response交给中间件的process_response方法处理,按中间件列表从下往上执行
		            response = self.process_response(request, response)
		        # 返回处理结果response
		        return response
       	'''
       	# django.core.handlers.base.BaseHandler._get_respons
       	'''
   	    def _get_response(self, request):
	        """
	        Resolve and call the view, then apply view, exception, and
	        template_response middleware. This method is everything that happens
	        inside the request/response middleware.
	        """
	        response = None
	
	        if hasattr(request, 'urlconf'):
	            urlconf = request.urlconf
	            set_urlconf(urlconf)
	            resolver = get_resolver(urlconf)
	        else:
	            resolver = get_resolver()
			# 路由匹配,获取到视图函数和视图函数的参数
	        resolver_match = resolver.resolve(request.path_info)
	        callback, callback_args, callback_kwargs = resolver_match
	        request.resolver_match = resolver_match
	
	        # Apply view middleware
	        # 执行装饰器的process_viewf方法
	        for middleware_method in self._view_middleware:
	            response = middleware_method(request, callback, callback_args, callback_kwargs)
	            if response:
	                break
	
	        if response is None:
	            wrapped_callback = self.make_view_atomic(callback)
	            try:
	                response = wrapped_callback(request, *callback_args, **callback_kwargs)
	            except Exception as e:
	                response = self.process_exception_by_middleware(e, request)
	
	        # Complain if the view returned None (a common error).
	        if response is None:
	            if isinstance(callback, types.FunctionType):    # FBV
	                view_name = callback.__name__
	            else:                                           # CBV
	                view_name = callback.__class__.__name__ + '.__call__'
	
	            raise ValueError(
	                "The view %s.%s didn't return an HttpResponse object. It "
	                "returned None instead." % (callback.__module__, view_name)
	            )
	
	        # If the response supports deferred rendering, apply template
	        # response middleware and then render the response
	        # 调用中间件的process_template_response方法,进行模板渲染前处理
	        elif hasattr(response, 'render') and callable(response.render):
	            for middleware_method in self._template_response_middleware:
	                response = middleware_method(request, response)
	                # Complain if the template response middleware returned None (a common error).
	                if response is None:
	                    raise ValueError(
	                        "%s.process_template_response didn't return an "
	                        "HttpResponse object. It returned None instead."
	                        % (middleware_method.__self__.__class__.__name__)
	                    )
	
	            try:
	            	# 渲染模板
	                response = response.render()
	            except Exception as e:
	                response = self.process_exception_by_middleware(e, request)
	
	        return response
       	'''
       	
        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()),
        ]
        # 上一篇我们提到TCPServer以WSGIRequestHandler作为处理请求的接口,
        # 在监听到访问请求后该接口将套接字信息封装到ServerHandler,
        # 并由ServerHandler的run方法将得到的socket信息和wsgiref.handlers.BaseHandler.start_response传递给WSGIHandler的__call__,
        # 该方法进行header处理,status状态码检验
        start_response(status, response_headers)
        # wsgiref.handlers.BaseHandler.start_response
        '''
        def start_response(self, status, headers,exc_info=None):
        	"""'start_response()' callable as specified by PEP 3333"""

	        if exc_info:
	            try:
	                if self.headers_sent:
	                    # Re-raise original exception if headers sent
	                    raise exc_info[0](exc_info[1]).with_traceback(exc_info[2])
	            finally:
	                exc_info = None        # avoid dangling circular ref
	        elif self.headers is not None:
	            raise AssertionError("Headers already set!")
	
	        self.status = status
	        self.headers = self.headers_class(headers)
	        status = self._convert_string_type(status, "Status")
	        assert len(status)>=4,"Status must be at least 4 characters"
	        assert status[:3].isdigit(), "Status message must begin w/3-digit code"
	        assert status[3]==" ", "Status message must have a space after code"
	
	        if __debug__:
	            for name, val in headers:
	                name = self._convert_string_type(name, "Header name")
	                val = self._convert_string_type(val, "Header value")
	                assert not is_hop_by_hop(name),\
	                       f"Hop-by-hop header, '{name}: {val}', not allowed"
	
	        return self.write
        '''
        if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
            response = environ['wsgi.file_wrapper'](response.file_to_stream)
        # 这里将得到的response返回给django.core.servers.basehttp.ServerHandler.run的self.result,
        # 最后交给self.finish_response()将访问结果通过self.wfile返回给请求访问的客户端。
        return response

由此可以看到django的访问过程经过如下:

Created with Raphaël 2.2.0 客户端(浏览器)发起TCP请求 TCPServer监听到请求 WSGIRequestHandler.handle ServerHandler.run WSGIHandler.__call__ WSGIRequest封装request 交给中间件的process_request 是否获取到response? 将request和response交给中间件的process_response response经过处理后通过self.wfile返回给客户端 根据路由匹配视图函数 交给中间件的process_view 交给具体视图 视图函数是否正常执行? 响应内容是否需要渲染模板? 交给中间件的process_template_response 交给具体render方法 渲染是否正确执行? 返回response 将request和response交给中间件的process_response response经过处理后通过self.wfile返回给客户端 交给中间件的process_exception 交给中间件的process_exception yes no yes no yes no yes no
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值