URLから実行するモジュールを判断して実行させたい

やりたかったことは2点。

  1. django & python で動的にモジュールを呼び出す
  2. python で可変引数を受け付ける関数を実現

というわけで「http://localhost:8000/api/image/set/」で「img/views.py の set()」が、「http://localhost:8000/api/image/own/list/」で「img/views.py の list()」が動作するようになるまでを。
(ownてのは後々、自分の画像って意味で使用したいから)

  • python manage.py startapp api」で api アプリケーションを作成
  • python manage.py startapp img」で img アプリケーションを作成
  • settings.py
# INSTALLED_APPS に以下を追記
    'api',
  • urls.py
urlpatterns = auth_patterns + patterns('',
    ('^admin/(.*)', admin.site.root),
    (r'^$', 'django.views.generic.simple.direct_to_template',
        {'template': 'main.html'}),

    (r'^api/', include('api.urls') ),  # コレを追記

    # Override the default registration form
    url(r'^account/register/$', 'registration.views.register',
        kwargs={'form_class': UserRegistrationForm},
        name='registration_register'),
) + urlpatterns
  • api/urls.py(新規作成)
# -*- coding: utf-8 -*-
from django.conf.urls.defaults import *

urlpatterns = patterns(
    'api.views'
    ,(r'(?P<path_info>.*)', 'action')
)
# -*- coding: utf-8 -*-
from django.http import HttpResponse

def action(request, path_info):
    path_list = path_info.split('/')
    module_name = getModuleName(path_list) + '.views'
    method_name = getMethodName(path_list)
    if hasattr(__import__(module_name).views , method_name):
        app = __import__(module_name)
        module = getattr(app.views, method_name)
        return module(request, {'path_list':path_list})
    return HttpResponse('実行するアプリケーションまたはメソッドが無い')

def getModuleName(path_list):
    modules = {
        'default' : 'index'
        , 'image' : 'img'
    }
    if modules.has_key(path_list[1]):
        return modules[path_list[1]]
    elif path_list[2] is not None and path_list[2] != '' and modules.has_key(path_list[2]):
        return modules[path_list[2]]
    else:
        return modules['default']

def getMethodName(path_list):
    if path_list[len(path_list)-1] != '' :
        name = path_list[len(path_list)-1]
    else:
        name = path_list[len(path_list)-2]
    return name
  • img/views.py
# -*- coding: utf-8 -*-
from django.http import HttpResponse

def index(*data):
    print 'img - default'
    return HttpResponse(None)

def set(*data):
    print 'img - set'
    for val in data:
        print type(val)
        print val
    return HttpResponse(None)

def list(*data):
    print 'img - list'
    for val in data:
        print type(val)
        print val
    return HttpResponse(None)

というわけで、動かしたいように動いてはくれた。

  • インポートする際に imp っていうモジュールもあるらしいけど __import__ 使ったほうがよさげ。具体的にどこがいいかはまだ不明。
  • 「(r'(?P.*)', 'action')」この「」を「」にすると「def action(request, text)」とできる。ふむ、何でもいいのか。
  • 関数を作るとき、引数に「*」を付けると、全てをタプル型として格納して受け取れる状態にしてくれる。
  • 引数に「**」を付けると、仮引数に対応していない引数を格納してくれるらしい。これはいつかテストする。

以下は参考


記載が雑だなあ…とは思います。