• django源码分析 请求流程


    一、从浏览器发出一个请求,到返回响应内容,这个过程是怎么样的?

    1. 浏览器解析输入的url

    2. 查找url对应的ip地址

    3. 通过ip地址访问我们的服务器

      1.  请求进入wsgi服务器(我在这里省略了可能存在的代理服务器,比如nginx)

      2.  wsgi服务器将请求包装后,传递给django应用

      3.  django应用根据请求路径找到相应的处理函数进行处理

      4.  处理完成后,django应用将响应返回给wsgi服务器

      5. wsgi服务器将django应用返回的响应包装后,返回响应

    4. 服务器返回响应内容,浏览器渲染输出

    二、django应用程序的处理入口

    wsgi服务通过wsgi协议和django应用进行通信,wsgi服务是server端,django应用是application,server端通过django提供的application_callable函数去调用djano应用,application_callable函数处理完成后,将响应返回给server

    django的application_callable函数在django.core.handlers.wsgi.py文件中,server服务端处理每个请求时会调用WSGIHandler这个类

    #wsgi.py文件

    class
    WSGIHandler(base.BaseHandler): request_class = WSGIRequest def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) 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 = 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 = list(response.items()) for c in response.cookies.values(): response_headers.append(('Set-Cookie', c.output(header=''))) start_response(status, response_headers) 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) return response

    三、django处理请求流程

    WSGIHandler类在初始化时,首先加载中间件,将要请求的函数 _get_response用中间件封装起来(中间件相当于装饰器),执行的时候,中间件就会执行

    
    
    # wsgi.py文件
    def load_middleware(self):
      ...

    self._view_middleware
    = [] self._template_response_middleware = [] self._exception_middleware = [] handler = convert_exception_to_response(self._get_response) for middleware_path in reversed(settings.MIDDLEWARE): middleware = import_string(middleware_path) try: mw_instance = middleware(handler) except MiddlewareNotUsed as exc:        ...

    handler = convert_exception_to_response(mw_instance) self._middleware_chain = handler

     接下来,就是请求调用WSGIHandler

    1. 实例化一个request_class

    2. 通过get_response获取请求,get_response最终会调用被中间件封装后的函数 _get_response 

    def _get_response(self, request):
        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
    
        ...
    
        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)
    
        ...
    
        return response

    _get_response函数中,首先会根据url找到要调用的视图函数 resolver_match = resolver.resolve(request.path_info),然后调用视图函数 response = wrapped_callback(request, *callback_args, **callback_kwargs)返回response(在_get_response里面也是会调用一些的中间件的)

    至此再将response返回给server,整个请求流程完毕

    下面是这个过程的流程图

    我也以一种函数的形式,写了一下这个流程

    def process_request(request)
        try:
            # 请求前的中间件
            response = pre_middleware(request)
            if response:
                return response
            
            # 视图中间件
            response = view_middleware(request, view_fun)
            
            if not response:
                try:
                    # 执行视图函数
                    reponses = view_fun(request)
                except:
                    # 异常中间件
                    responser = exception_middleware()
            
            if hasattr(response, 'render'):
                # 模板中间件
                response = template_middleware(response)
                try:
                    response = response.render()
                except:
                    response = exception_middleware()
            
            # 请求后的中间件
            response = post_middleware(request, response)
                
        except:
            response = exception()
            
        return response

    四、总结

    django对于一个请求,主要过程就是寻找请求对应的视图函数,调用被中间件封装后的视图函数,返回响应。

  • 相关阅读:
    公司的CMS参数
    Kafka 如何保证消息可靠性
    我来了
    spring解决乱码
    mybatis反向工程
    Unicode控制字符
    功能跟进记录
    创建IDataProvider实例
    腾讯2016研发工程师笔试题36车 6跑道 没有计时器 最少要几次取前三
    .net mvc下拉列表DropDownList控件绑定数据
  • 原文地址:https://www.cnblogs.com/time-read/p/10650988.html
Copyright © 2020-2023  润新知