基于Django框架的forward实现

目前基于 Django 开发的Web应用存在过多的302跳转,导致服务器性能浪费。想到Java容器有 request.getDispatcher().forward(),就动手自己来实现。

首先,要了解下Django处理http请求的流程。网上很多文档,官方的当然最好,中文的可以看这里。看了之后,觉得forward不需要再多走一遍中间件。实现的大致逻辑:根据项目中配置的Django的urlconf,解析出forward后的view方法,然后调用即可。如果forward中德url新增了queryString的参数,则修改forward之前的httpRequest。这里需修改两个参数,request.META[‘QUERY_STRING’]和request.GET,但由于QueryDict是immutable的,所以需要做特殊处理,具体看代码。

#-*-coding=utf-8-*-
import urlparse
from django.conf import settings
from django.core import urlresolvers

def forward(url, request):
    '''
    非跳转型重定向 -- 服务端将请求转给另一个View响应,客户端不会察觉
    '''
    try:
        # Update query string
        query_str = ""
        i = url.find('?')
        if i > -1:
            url, query_str = url[:i], url[i + 1:]

        request.META['QUERY_STRING'] += '&' + query_str
        request.GET = request.GET.copy()
        query_dict = urlparse.parse_qs(query_str)
        for k, v in query_dict.items():
            if v and len(v) == 1:
                query_dict.update({k: v[0]})

        request.GET.update(query_dict)

        # Analyze url
        urlconf = settings.ROOT_URLCONF
        urlresolvers.set_urlconf(urlconf)
        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf)

        resolver_match = resolver.resolve(url)
        callback, callback_args, callback_kwargs = resolver_match
        request.resolver_match = resolver_match

        return callback(request, *callback_args, **callback_kwargs)
    finally:
        # Reset URLconf for this thread on the way out for complete
        # isolation of request.urlconf
        urlresolvers.set_urlconf(None)

仓促间完成的代码,如发现bug,或有更好的方法,一起交流吧。