Django从请求到响应的处理流程深入剖析(源码分析)

Django从请求到响应的处理流程深入剖析(源码分析)_第1张图片众所周知,django项目启动命令:python manage.py runserver

那么,执行runserver命令之后到底django做了哪些事情呢(uWSGI运行Django项目也一样)?

1、首先,django执行runserver.Command(BaseCommand)中的execute()函数。

2、execute()通过self.handle(*args, **options)来调用runserver.Command.inner_run()方法。在inner_run()方法中又做了两件事情:

  • 调用django.core.wsgi.get_wsgi_application()函数来获取WSGIHandler处理器对象
  • 通过调用basehttp.run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer)方法,创建WSGIServer实例,并通过调用socketserver.Baseserver.serve_forever()方法,实现请求的监听。

至此,django项目已启动,并且实现了端口监听,那么一个请求的到来django又是如何处理的呢?

1、首先,WSGIServer实例会监听到一个请求的到来,WSGIServer通过set_app方法设置一个可调用(callable)的对象作为application,并负责创建一个WSGIRequestHandler实例对象,并使用其handler()方法来处理请求(其实最终是调用wsgiref.handlers.BaseHandler中的run方法处理,唯一参数为application可调用对象,也就是WSGIHandler处理器对象)。

2、至此,我们通过run(WSGIHandler)才真正进入了django世界,WSGIHandler则真正作为django处理请求与生成响应的对象。

3、回头再看WSGIHandler实例对象,由django.core.handlers.wsgi.WSGIHandler实例化而来,源码如下:

class WSGIHandler(base.BaseHandler):
    request_class = WSGIRequest

    def __init__(self, *args, **kwargs):
        super(WSGIHandler, self).__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 = [(str(k), str(v)) for k, v in response.items()]
        for c in response.cookies.values():
            response_headers.append((str('Set-Cookie'), str(c.output(header=''))))
        start_response(force_str(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

WSGIHandler首先调用它自己的load_middleware方法,加载所有列在MIDDLEWARE_CLASSES中的middleware类并且内省它们。

当这个WSGIHandler实例对象被调用时,会进入__call__方法。

现在处理器已经准备好真正开始处理了,因此它给调度程序发送一个信号request_started(Django内部的调度程序允许各种不同的组件声明它们正在干什么,并可以写一些代码监听特定的事件。关于这一点目前还没有官方的文档,但在wiki上有一些注释),接下来它实例化一个django.http.HttpRequest的子类。

根据不同的处理器,可能是django.core.handlers.modpython.ModPythonRequest的一个实例,也可能是django.core.handlers.wsgi.WSGIRequest的一个实例。需要两个不同的类是因为mod_pythonWSGI APIs以不同的格式传入request信息,这个信息需要解析为Django能够处理的一个单独的标准格式。
一旦一个HttpRequest或者类似的东西存在了,处理器就调用它自己的get_response方法,传入这个HttpRequest作为唯一的参数。这里就是几乎所有真正的活动发生的地方。

4、Middleware开始工作了!

get_response做的第一件事就是遍历处理器的_request_middleware实例变量并调用其中的每一个方法,传入HttpRequest的实例作为参数。

关于Middleware详细的执行流程,请参考 django中间件解析

5、处理器下一步会尝试解析请求的URL。它在配置文件中寻找一个叫做ROOT_URLCONF的配置,用这个配置加上根/,作为参数来创建django.core.urlresolvers.RegexURLResolver的一个实例,然后调用它的resolve方法来解析请求的URL路径。

6、一旦知道了所需的 view function和相关的参数,处理器就会查看它的_view_middleware列表,并调用其中的方法,传入 HttpRequst,view function,针对这个view的位置参数列表和关键字参数字典。

7、进入View了!

如果处理过程这时候还在继续的话,处理器会调用view function。一般来说,views会使用Djangodatabase API来创建、检索、更新和删除数据库的某些东西,还会加载并渲染一个模板来呈现一些东西给最终用户。

8、view中有异常!

发生了异常,那么get_response将遍历它的_exception_middleware实例变量并调用那里的每个方法,传入HttpResponse和这个exception作为参数。如果顺利,这些方法中的一个会实例化一个HttpResponse并返回它。

9、至此,django已经完成了接收一个请求,并生成响应返回给客户端。

 

你可能感兴趣的:(Django)