Django的请求处理过程分析

Django请求处理过程的逻辑基本上在django.core.handlers.base.BaseHandler这个类的get_response方法中了,为了简单起见,我只是截取了这个类的部分代码,并把相应的过程作为注释写在代码里,说明问题即可。(本代码截取于Django 1.4)

1. 接收到一个请求(初始化)
2. 应用请求中间件(中间件第一回合)
3. 应用视图中间件(中间件第二回合)
4. 调用用户视图方法
5. (如果有异常发生的话)应用异常处理中间件(中间件第三回合)
6. (如果符合要求的话)应用模板中间件(中间件第四回合)
7. 应用响应中间件(中间件第五回合)
8. (如果中间没有异常发生的话)最终响应用户请求

代码分析如下:

class BaseHandler(object):
    ...
    def get_response(self, request):
        from django.core import exceptions, urlresolvers
        from django.conf import settings

        try:
            urlconf = settings.ROOT_URLCONF
            urlresolvers.set_urlconf(urlconf)
            resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
            try:
                response = None
                # 应用请求中间件(第一回合)
                # 这是中间件的第一回合,一般来说,中间件返回None,则表示继续往下一级处理,否
                # 则,响应已完成,不再进行处理,因此每次处理之前,都有"response is None"的
                # 判断。
                for middleware_method in self._request_middleware:
                    response = middleware_method(request)
                    if response:
                        break

                if response is None:
                    # 处理Request对象中的urlconf,可以来实现类似URL重写的功能
                    if hasattr(request, urlconf):
                        # Reset url resolver with a custom urlconf.
                        urlconf = request.urlconf
                        urlresolvers.set_urlconf(urlconf)
                        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)
                    # 提取出用户视图方法,随后调用
                    callback, callback_args, callback_kwargs = resolver.resolve(
                            request.path_info)

                    # 应用视图中间件(第二回合)
                    for middleware_method in self._view_middleware:
                        response = middleware_method(request, callback, 
                                callback_args, callback_kwargs)
                        if response:
                            break

                if response is None:
                    # 调用用户视图方法
                    try:
                        response = callback(request, *callback_args,
                                **callback_kwargs)
                    except Exception, e:
                        # 应用异常处理中间件(第三回合)
                        # 这里的异常处理中间件只处理调用户视图产生的异常,并不是所有的异常。
                        for middleware_method in self._exception_middleware:
                            response = middleware_method(request, e)
                            if response:
                                break
                        if response is None:
                            raise

                # 完成以上步骤后,response不应该为空了,否则就要抛出异常
                if response is None:
                    try:
                        view_name = callback.func_name # If it's a function
                    except AttributeError:
                        view_name = callback.__class__.__name__ + '.__call__'
                    raise ValueError(The view %s.%s didn't return an
                            HttpResponse object.
                            % (callback.__module__, view_name))

                # 应用模板中间件(第四回合)(可选)
                # 注意,这里应用模板中间件是无条件的,每个中间件都调用了,所以for语句中没有
                # "if response: break"这样的语句。
                if hasattr(response, 'render') and callable(response.render):
                    for middleware_method in self._template_response_middleware:
                        response = middleware_method(request, response)
                    response = response.render()

            except http.Http404, e:
                logger.warning('Not Found: %s', request.path,
                            extra={
                                'status_code': 404,
                                'request': request
                            })
                if settings.DEBUG:
                    from django.views import debug
                    response = debug.technical_404_response(request, e)
                else:
                    try:
                        callback, param_dict = resolver.resolve404()
                        response = callback(request, **param_dict)
                    except:
                        try:
                            response = self.handle_uncaught_exception(request,
                                    resolver, sys.exc_info())
                        finally:
                            signals.got_request_exception.send(
                                    sender=self.__class__, request=request)
            except exceptions.PermissionDenied:
                logger.warning(
                    'Forbidden (Permission denied): %s', request.path,
                    extra={
                        'status_code': 403,
                        'request': request
                    })
                try:
                    callback, param_dict = resolver.resolve403()
                    response = callback(request, **param_dict)
                except:
                    try:
                        response = self.handle_uncaught_exception(request,
                                resolver, sys.exc_info())
                    finally:
                        # 向系统发出处理异常的信号
                        signals.got_request_exception.send(
                                sender=self.__class__, request=request)
            except SystemExit:
                raise
            except: # Handle everything else, including SuspiciousOperation,
                # 向系统发出处理异常的信号
                signals.got_request_exception.send(sender=self.__class__,
                        request=request)
                response = self.handle_uncaught_exception(request, resolver,
                        sys.exc_info())
        finally:
            # 重置URLconf
            urlresolvers.set_urlconf(None)

        try:
            # 应用响应中间件(第五回合),也是每个中间件都调用了
            for middleware_method in self._response_middleware:
                response = middleware_method(request, response)
            # 对response对象的一些补丁处理
            response = self.apply_response_fixes(request, response)
        except:
            # 向系统发出处理异常的信号
            signals.got_request_exception.send(sender=self.__class__,
                    request=request)
            # 最终会发出一个代表异常的响应
            response = self.handle_uncaught_exception(request, resolver,
                    sys.exc_info())

        return response
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值