您的位置:首页 > 编程语言 > ASP

让django像Asp.Net Mvc一样自动匹配Controller和Action

2012-06-04 22:19 357 查看
Asp.Net Mvc 中,我们可以通过配置如下路由,允许从Url中匹配每段路径到Area, Controller和Action中,在尝试使用了django之后,发现django的路由系统更加灵活,允许通过正则匹配任意Url到任意View,但如果希望通过在Url路径中指定要访问的app, view,就比较麻烦,我下面的尝试,通过匹配Url,使用python自省(反射)查找特定View方法并返回该方法执行结果,建立了一个简单的python路由规则。

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

}


代码列表-1 Asp.Net Mvc路由配置

为了不影响现有逻辑,我在原django项目中新建了一个routed app,在该app中配置路由,下面是django项目结构

DjangoApp
|-urls.py
|-settings.py
|-manage.py
|-views.py
|-routed
|-urls.py
|-models.py
|-tests.py


代码列表-2 django项目结构

首先需要改动的是项目的根urls.py,凡是所有以"routed"开头的url,都交给routedapp下的urls.py来处理

(r'^routed/', include('DjangoApp.routed.urls')),


代码列表-3 项目根urls.py的更改

然后,在routed app的urls.py中,添加对url按照路由进行解析的规则

from django.conf.urls.defaults import *
from DjangoApp.routed.viewstart import start

urlpatterns = patterns('',
(r'^(?P<controller>\w+)?/(?P<action>\w+)?/(?P<parameter>.+)?$', start),
)


代码列表-4 routed app中urls.py的更改

在这个规则中,将所有类似"/routed/controllerabc/actionxyz/parm123"的url都指向viewstart.py中的start方法处理

import inspect
from util.response import *
from util.common import *

def start(request,controller,action,parameter):
#initialize controller, execute action with parameter
prefix = 'DjangoApp.routed.controllers.'

namespace = prefix + controller
__import__(namespace)
module = common.importmodule(namespace)

methods = [k for k,v in inspect.getmembers(module) if k == action]
if len(methods) <= 0:
return response.http404()

return getattr(module,methods[0])(request)


代码列表-5 viewstart.py

在viewstart.py中,根据匹配得到的Controller查找python模块,然后过滤用inspect.getmembers得到的方法,找到对应Action并执行之,python中的反射非常易用,内置方法__import__可动态引入需要的模块,globals方法可以返回传入的字符串代表的对象,getattr方法的返回值直接加上括号即可执行。代码中,util.common中封装了由字符串反射得到对象实例的方法,util.response封装了各种http response的方法,参考代码列表-6、代码列表-7。

import os
import sys

class common:
@classmethod
def importmodule(self,namespace):
components = namespace.split('.')
if len(components) == 1:
return globals()[namespace]

module = __import__(components[0])
for compent in components[1:]:
module = getattr(module, compent)

return module


代码列表-6 common.py

from django.template import Context
from django.template.loader import get_template
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.core import serializers

class response:
@classmethod
def json(self,object):
json = serializers.serialize("json", object)
return HttpResponse(json,'application/json')

@classmethod
def xml(self,object):
xml = serializers.serialize("xml", object)
return HttpResponse(xml,'application/xml')

@classmethod
def falt(self,errormessage=''):
return self.json({"errorcode":"500","message":errormessage if errormessage else ''})

@classmethod
def view(self,view,view_model=None):
view_path = view+'.view'
return render_to_response(view_path,view_model)

@classmethod
def text(self,text):
return HttpResponse(text)

@classmethod
def http404(self):
return self.view('http404')


代码列表-7 response.py

最后,我们只要在routed app下创建controllers文件夹,然后创建controller即可通过controller名称对应的Url访问,如创建book.py

from util.response import *
from routed.models import Book

def list(request):
books = Book.objects.all()
return response.json(books)


代码列表-8 book.py

输入book controller中的list action对应的url http://localhost/routed/book/list 试试看吧。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: