djangoをAspのようにします.Net Mvcと同様にControlとActionを自動的にマッチング
4522 ワード
Asp.Net Mvcでは、UrlからArea、Controller、Actionまでの各パスのマッチングを可能にするルーティングを構成し、djangoを使用しようとした後、djangoのルーティングシステムがより柔軟であることを発見し、任意のUrlを任意のViewに正規マッチングすることを可能にしたが、Urlパスでアクセスするapp、viewを指定することを希望すると面倒になり、私の次の試みは、Urlをマッチングすることによって、python自省(反射)を使用して特定のViewメソッドを検索し、その実行結果を返し、簡単なpythonルーティングルールを確立します.
コードリスト-1 Asp.Net Mvcルーティング構成
既存のロジックに影響を及ぼさないように、元のdjangoプロジェクトにrouted appを新規作成しました.このappでルーティングを構成します.次はdjangoプロジェクト構造です.
コードリスト-2 djangoプロジェクト構造
まず変更する必要があるのはプロジェクトのルートurlsです.py、「routed」で始まるurlはすべてroutedappの下のurlsに渡されます.pyで処理する
コードリスト-3プロジェクトルートurls.pyの変更
そして、routed appのurls.pyでurlをルーティングするルールを追加
コードリスト-4 routed appのurls.pyの変更
このルールでは、「/routed/controllerabc/actionxyz/parm 123」のようなurlはviewstartを指す.pyでのstartメソッド処理
コードリスト-5 viewstart.py
viewstartでpyでは、一致するControllerに基づいてpythonモジュールを検索し、inspectをフィルタする.getmembersで得られたメソッドは,対応するActionを見つけて実行し,pythonでの反射が非常に使いやすく,内蔵メソッド_import__必要なモジュールを動的に導入することができ、globalsメソッドは入力された文字列が表すオブジェクトを返すことができ、getattrメソッドの戻り値は直接かっこで実行できます.コード中、util.commonには、文字列の反射により得るオブジェクトのインスタンスをカプセル化する方法、util.responseは、コードリスト−6、コードリスト−7を参照する様々なhttp responseをカプセル化する方法である.
コードリスト-6 common.py
コードリスト-7 response.py
最後に、routed appの下にcontrollersフォルダを作成し、controllerを作成するだけで、bookの作成など、controller名に対応するUrlからアクセスできます.py
コードリスト-8 book.py
book controllerのlist action対応url http://localhost/routed/book/listを入力してみましょう.
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/parm 123」のような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は、コードリスト−6、コードリスト−7を参照する様々なhttp responseをカプセル化する方法である.
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を作成するだけで、bookの作成など、controller名に対応するUrlからアクセスできます.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を入力してみましょう.