ちょっとしたWebAPIなどを作りたい場合、出来るだけコストのかからない方法で作りたいと思うのが、めんどくさがり屋の性。
Web.pyは、そんなめんどくさがり屋のあなたにピッタリな環境をご提供します!
いや、どうでもいいんですけどね・・・
そんな(どんな)Web.pyですが、パスハンドラーごとにクラスを定義しないといけないようだし、cookbook見るとMVCのサンプルとか、いやそんな立派なもの作る気ないんですよーとか、ほんと面倒なので(ちなみに仕事ではありませんので・・)ちょっとしたラッパーを描いてみました。
結論から申し上げれば、デコレーターに悩まされるくらいなら普通に描いたほうが早いよね!程度のものでした。
import web
render = web.template.render('template')
class path:
def __init__(self):
self._map = []
self._count = 1
def addPath(self, method, pathstr, func):
def invoker(*args):
return func(*args)
self._map.extend([
'/' + pathstr,
type(method + str(self._count), (), {
method : lambda self, *args: invoker(*args)
})
])
self._count += 1
def app(self):
return web.application(tuple(self._map), globals())
def get(self, pathstr):
def builder(func):
self.addPath('GET', pathstr, func)
return func
return builder
def post(self, pathstr):
def builder(func):
self.addPath('POST', pathstr, func)
return func
return builder
def arguments(self, *args, **kw):
def ptr(func):
def invoker():
values = [web.input()[x] for x in args]
for k, v in kw.iteritems():
i = list(args).index(k)
values[i] = v(values[i])
return func(*values)
return invoker
return ptr
def result(self, template, head= 'text/html'):
def ptr(func):
def invoker(*args):
web.header('Content-Type', head)
return getattr(render, template)(*func(*args))
return invoker
return ptr
path = path()
以外に長いです。結構な割合でお邪魔いたします。 使い方はこのような。
テンプレート:result.xml
$def with(retcode, msg)
<?xml version="1.0"?>
<Result>
<Code>$retcode</Code>
<message>
<![CDATA[$msg]]>
</message>
</Result>
ハンドラー実装
@path.get('test/(\d+)') //パス指定
@path.result('result', 'text/xml') //テンプレート指定
def test(arg):
return True, arg
app = path.app()
if __name__ == "__main__":
app.run()
クエリーストリング[bid]からブログクラスのインスタンスを引数にする
class Blog:
....
@path.get('blog')
@path.arguments('bid', bid= Blog)
@path.result('blog')
def blog(blog):
return blog //テンプレート任せ
例えばDrupalでもメニューシステムというコアの中でも要の部分がパスハンドリングを担っているように、こういった部分を如何にスマートに書けるかも、CMSだったりCMFだったりの使いやすさに影響するのではないのかなと思ってます。
ちなみに、Drupalでは、クエリーストリングではなく、パスに対して上記のようなオブジェクトローダーを絡ませる機能と、アクセス権限があるか否かの判定を行うことが出来ます。