论坛首页 编程语言技术论坛

django源代码分析三 走向现代

浏览 4909 次
精华帖 (0) :: 良好帖 (2) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-11-22  
 response = callback(request, *callback_args, **callback_kwargs)
 

   前两篇估计不怎么解馋——没有涉及到任何关于web开发的东西。呵呵,其实我的这些文章不是要写怎么用django,而是以一种探索的心态深入到django的内部,不断的发现它的各种扩展点,各种有用的工具。

   闲言少叙,切入正题。我们要了解当一个web请求自客户端提交到服务器端,都经过了那些“磨难”。首先让我们找到这一切的根源—— django.core.management.commands.runserver.py。这个启动了django的web server。

   在runserver.py的59行

 handler = AdminMediaHandler(WSGIHandler(), admin_media_path)
run(addr, int(port), handler)

 在第59行,我们不难发现,django底层是基于WSGI的,它的application有了两个,一个是AdminMediaHandler 提供后台管理的静态页面的访问,一个是WSGIHandler,这个是最主要的,负责除实际的views分发。run函数是定义在basehttp.py 中的

def run(addr, port, wsgi_handler):
    server_address = (addr, port)
    httpd = WSGIServer(server_address, WSGIRequestHandler)
    httpd.set_app(wsgi_handler)
    httpd.serve_forever()

 WSGIServer和WSGIRequestHandler是django基于python HTTPServer写的一个WSGI的服务器。有兴趣的朋友可以参考一下这个http://docs.python.org/library /basehttpserver.html 这里是python内置的一些服务器实现。这些内容也够讲一阵的,这里我们就不岔开话题了。回头继续看我们的代码,WSGIHandler是“一切”的开 始,在__call__方法实际进行“分发”。

if self._request_middleware is None:
            self.initLock.acquire()
            # Check that middleware is still uninitialised.
            if self._request_middleware is None:
                self.load_middleware()
            self.initLock.release()

首先看到的是这个代码段,这里进行了django middleware有人翻译成中间件,我觉得这是一种只译的方式不可取;拦截器更贴切。这段代码中,首先进行了加锁,然后加载拦截器,然后释放锁;这里 加锁的目的是因为__call__是线程不安全的。我们跟进load_middleware里面,可以看到django的拦截器是如何被加载的,我们看 53行,

            if hasattr(mw_instance, 'process_request'):
                request_middleware.append(mw_instance.process_request)
            if hasattr(mw_instance, 'process_view'):
                self._view_middleware.append(mw_instance.process_view)
            if hasattr(mw_instance, 'process_response'):
                self._response_middleware.insert(0, mw_instance.process_response)
            if hasattr(mw_instance, 'process_exception'):
                self._exception_middleware.insert(0, mw_instance.process_exception)

 django提供了process_reuqeest、process_view、process_response、 process_exception,这几种拦截点,这比WSGI的拦截更加的细致。在django.middleware中定义了django内置的一 些拦截装置,有兴趣的朋友不妨参考一下。

        signals.request_started.send(sender=self.__class__)
        try:
            try:
                request = self.request_class(environ)
            except UnicodeDecodeError:
                response = http.HttpResponseBadRequest()
            else:
                response = self.get_response(request)

                # Apply response middleware
                for middleware_method in self._response_middleware:
                    response = middleware_method(request, response)
                response = self.apply_response_fixes(request, response)
        finally:
            signals.request_finished.send(sender=self.__class__)

 注意signal这里,这个是django的另一个拦截点,这里我们看到,会发送request_started、 request_finished这两个消息,其实除了这两个,django还有一些model的消息,可以参考这里 http://docs.djangoproject.com/en/dev/topics/signals/

最重要的是这一句

response = self.get_response(request)

 这个调用了父类BaseHandler的get_response,在82句是

callback, callback_args, callback_kwargs = resolver.resolve(
                    request.path_info)

 92句

 response = callback(request, *callback_args, **callback_kwargs)

 我们已经看到了“希望”,92句开启了views的执行。get_response还涉及到URL的解析,有兴趣的朋友可以仔细阅读。

论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics