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ルーティングルールを確立します.
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を入力してみましょう.