django源码分析:HTTP请求过程(wsgi)

本文详细分析了Django在处理HTTP请求时的流程,从runserver启动的WSGIServer,到WSGIRequestHandler如何处理请求,再到get_handler()方法获取WSGI应用,最后讲解了URL解析、视图函数的as_view()方法及请求响应的处理。通过对Django源码的解析,揭示了请求如何变为响应的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文环境python3.5.2,django1.10.x系列
python manage.py runserver 命令启动本地调试服务器后,接着要分析一下django对请求request的整个处理过程,

在此感谢在django源码学习中 小屋子大侠 的帮助,
小屋子大侠 博文地址:https://blog.youkuaiyun.com/qq_33339479/article/category/6800733

一、创建WSGIServer

上一节讲到在使用runserver运行Django项目,在启动时会调用django.core.servers.basehttp中的run()方法,创建一个django.core.servers.basehttp.WSGIServer类的实例,之后调用其serve_forever()方法启动HTTP服务。run方法的源码如下:

def run(addr, port, wsgi_handler, ipv6=False, threading=False): 
  server_address = (addr, port)                                                         # 服务端监听的地址和端口
  if threading:                                                                         # 如果多线程运行
    httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})  # 创建WSGIServer服务器,生成一个
  else:
    httpd_cls = WSGIServer
  httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)                      # 实例化该类
  # Sets the callable application as the WSGI application that will receive requests
  httpd.set_app(wsgi_handler)                                                           # 设置客服务端的处理handler, 即application
  httpd.serve_forever()

如上,我们可以看到:在创建WSGIServer实例的时候会指定HTTP请求的Handler,上述代码使用WSGIRequestHandler。当用户的HTTP请求到达服务器时,WSGIServer会创建WSGIRequestHandler实例,使用其handler方法来处理HTTP请求(其实最终是调用wsgiref.handlers.BaseHandler中的run方法处理)。WSGIServer通过set_app方法设置一个可调用(callable)的对象作为application,上面提到的handler方法最终会调用设置的application处理request,并返回response。

其中,WSGIServer继承自wsgiref.simple_server.WSGIServer,而WSGIRequestHandler继承自wsgiref.simple_server.WSGIRequestHandler,wsgiref是Python标准库给出的WSGI的参考实现。

class WSGIServer(HTTPServer):                                                           # WSGIServer继承自HTTPServer,HTTPServer继承自TCPServer

    """BaseHTTPServer that implements the Python WSGI protocol"""

    application = None

    def server_bind(self):
        """Override server_bind to store the server name."""
        HTTPServer.server_bind(self)
        self.setup_environ()

    def setup_environ(self):                                                            # 设置env环境参数
        # Set up base environment
        env = self.base_environ = {}
        env['SERVER_NAME'] = self.server_name
        env['GATEWAY_INTERFACE'] = 'CGI/1.1'
        env['SERVER_PORT'] = str(self.server_port)
        env['REMOTE_HOST']=''
        env['CONTENT_LENGTH']=''
        env['SCRIPT_NAME'] = ''

    def get_app(self):                                                                  # 获得处理器handler
        return self.application

    def set_app(self,application):                                                      # 设置处理器handler
        self.application = application

二、处理Request

第一步中说到的application,即为django.core.management.commands.runserver中的get_handler()方法

def get_internal_wsgi_application():
    """
    Loads and returns the WSGI application as configured by the user in
    ``settings.WSGI_APPLICATION``. With the default ``startproject`` layout,
    this will be the ``application`` object in ``projectname/wsgi.py``.

    This function, and the ``WSGI_APPLICATION`` setting itself, are only useful
    for Django's internal server (runserver); external WSGI servers should just
    be configured to point to the correct application object directly.

    If settings.WSGI_APPLICATION is not set (is ``None``), we just return
    whatever ``django.core.wsgi.get_wsgi_application`` returns.
    """
    from django.conf import settings                                                   # 加载生成project时生成的setting文件
    app_path = getattr(settings, 'WSGI_APPLICATION')                                   # 检查settings配置文件中是否设置“WSGI_APPLICATION”
    if app_path is None:                                                               # 如果没有设置,就使用默认的application
        return get_wsgi_application()

    try:
        return import_string(app_path)                                                 # 如果有设置,就返回设置的application
    except ImportError as e:
        msg = (
            "WSGI application '%(app_path)s' could not be loaded; "
            "Error importing module: '%(exception)s'" % ({
                'app_path': app_path,
                'exception': e,
            })
        )
        six.reraise(ImproperlyConfigured, ImproperlyConfigured(msg),
                    sys.exc_info()[2])

当settings文件中未设置WSGI_APPLICATION,就会使用django默认的内部wsgi方法,其中,get_wsgi_application()方法就是调用此方法,该函数在django.core.wsgi.py文件中

def get_wsgi_application():
    """
    The public interface to Django's WSGI support. Should return a WSGI
    callable.

    Allows us to avoid making django.core.handlers.WSGIHandler public API, in
    case the internal WSGI implementation changes or moves in the future.
    """
    django.setup(set_prefix=False)                                                   # 加载django初始环境
    return WSGIHandler()                                                             # 返回WSGI处理器

此方法在加载django处理化环境后,返回一个WSGIHandler类,下面我们看看这个处理器中的代码

class WSGIHandler(base.BaseHandler):
    request_class = WSGIRequest                                                 # 调用WSGIResquest对象

    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)    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值