Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

werkzeug その2(Routing基礎)

前回とりあえずテスト用サーバの起動、何かを表示するまでをやった。
早速Requestを作って云々したいところだけど、先にRouting部を見ていく。

Routing System

Routing SystemとはURLと実処理である関数の紐づけする仕組みの事。
werkzeugはこの機能も提供している。
もちろんスクラッチから組み上げる事ができるので既にあるRoutingライブラリである、Routesなどを使う事も可能
である。(絶対に使わないけど)
どのURLにアクセスしたRequest云々をどの関数に渡すか?などを決める重要な仕組みになるので先に実装しておく。

主なRoutingの定義方法は2種類ある。

  • URLと関数のmappingを全体(サブ)まとめて定義する方法
  • 関数にデコレータでURLをmappingする方法

djangoなどはまとめて定義する方法、TGなんかは下の方法でmappingを行う。
(仕組みがわかっていればどちらのスタイルも簡単に実現できる。)
werkzeugの公式チュートリアルではTGスタイルでmappingを定義する方法が紹介されている。
もし、そちらの方が好きな方は参考にするといい。
今回はdjangoのようにまとめて定義する方法で実装してみたいと思う。

Map, Rule

werkzeugはURLと遂になる情報(endpoint)をMapクラスで定義する。

簡単な例

from werkzeug.routing import Map, Rule

url_map = Map([
    Rule('/', endpoint='index'),
    Rule('/entry/<int:id>/', endpoint='entry')
    ])

urls = url_map.bind('example.com', '/')

print urls.match('/')
# ('index', {})

print urls.match('/entry/1/')
# ('entry', {'id':1})

print urls.match('/entry/1')
# RequestReirect

print urls.match('/hoge/1')
# NotFound!!

MapにRuleのリストを入れて定義し、matchで評価する。
(実際使う際にはenviron軽油のマッチングになるけど)

Ruleにはパターン、endpointを指定する。
werkzeugのパターンは独自形式となっており、

形式で定義する。
(定義を見るとなんとなく感じが掴めると思う)

djangoのように変態的な正規表現ではない。
mappingで使う正規表現はよほどのケースがない限り大体のパターンが決まってるのでこうなってるのだと思われる。
またconverterも組み込みである程度用意されている。
独自のパターンマッチングを行いたい場合には自作のconverterを仕込んで拡張することが可能だ。

マッチするとendpointとURLの定義でマッチした辞書を返す。
(entry部参照)
スラッシュなしのケースではちゃんとスラッシュありへのRedirectの情報も返してくれる。
見つからないケースではNotFoundが返る。

Submount, EndpointPrefix

mapping機能周りにはその他色々と便利な機能がある。

/blog/entry/
/blog//
/blog//
/blog///id:date/

のようなmappingを持ったblogアプリケーションを設計したとする。
毎回/blog/とか頭にアプリケーションの名前をつけて定義しないといけないのはしんどい。
そういう場合にはSubmount, EndpointPrefixを使う。

from werkzeug.routing import Map, Rule, EndpointPrefix, Submount

url_map = Map([
    EndpointPrefix('blog.', [Submount('/blog', [
        Rule('/', endpoint='index'),
        Rule('/entry/<int:id>/', endpoint='entry')
    ])])])

urls = url_map.bind('example.com', '/')

print urls.match('/blog/')
#('blog.index', {})

print urls.match('/blog/entry/1/')
#('blog.entry', {'id':1})

Submountに入れたRuleはSubmountの第1引数で指定したURLと結合されたRuleになる。
またEndpointPrefixは同様にendpointを結合する。
この機能はサブアプリケーションを構築する際に重宝する。

RuleTemplate

RuleTemplateは文字通りある一定のRule群をTemplate化しておける機能である。

from werkzeug.routing import Map, Rule, RuleTemplate

resource = RuleTemplate([
    Rule('/$name/', endpoint='$name.index'),
    Rule('/$name/entry/<int:id>/', endpoint='$name.entry')
    ])

url_map = Map([resource(name='user'), resource(name='page')])
urls = url_map.bind('example.com', '/')

print urls.match('/user/')
print urls.match('/page/')
print urls.match('/user/entry/1/')
print urls.match('/page/entry/1/')

RuleTemplateを使えば同じ記述は2度書かなくて済む。
djangoのadminのようなマスメン系の機能を作る際にとても重宝する。
この機能はSubmount, EndpointPrefixの代わりに使うこともできる。

Routing機能の主な機能を紹介した。
werkzeugのRoutingはシンプルだがとても柔軟で強力だ。
(RuleTemplateなど)

次回はRoutingを組み込んで動かしてみる。