Using Routes with TurboGears 実践

無事に使えた。各Controllerのdefaultメソッドでハンドリングする方法にはなんとなく違和感を持っていたけど、Routesはしっくりくる。エレガント。

例えばこんなルールとアクションがあったとき。

m.connect('users/:user', controller='users', action='user_summary')

users Controllerはこんな風になってる。

class UsersDir:
    @expose(template=".templates.user_summary")
    def user_summary(self, user):
        try:
            user = User.by_user_name(user)
        except SQLObjectNotFound:
            raise cherrypy.NotFound

        # ...
        return dict()

user_summaryメソッドの引数userに渡ってくるのは文字列なんだけど、欲しいのはUserオブジェクトなわけで。ユーザーが存在するかのチェックもしないといけない。上記のように書くと引数やアクションが増えてくると悲惨なことになる。

というわけで、ここはvalidatorで。

class ValidUserName(validators.FancyValidator):
    def _to_python(self, value, state):
        try:
            user = User.by_user_name(value)
            return user
        except SQLObjectNotFound:
            raise cherrypy.NotFound

class UsersDir:
    @expose(template=".templates.user_summary")
    @validate(validators={'user': ValidUserName()})
    def user_summary(self, user):
        # ...
        return dict()

Widgets.Formとの併用も問題無し。うーん、満足。