コメントに返信 | Color Balance

コメントに返信

ちょっとした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では、クエリースト­リングではなく、パスに対して上記のようなオブジェ­クトローダーを絡ませる機能と、アクセス権限がある­か否かの判定を行うことが出来ます。

返信

このフィールドの内容は公開されません。
  • ウェブページアドレスとメールアドレスを自動的にリンクに変えます。
  • 使用できるHTMLタグ: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • 改行と段落付けは自動的に行われます。

書式の詳細

CAPTCHA
この問題はユーザが人間であるかどうかをテストし、スパムによる自動投稿を防ぐためのものです。
イメージ CAPTCHA
Enter the characters shown in the image.