コントローラーの構築

コントロラーは、リクエストがウェブサービスに来たときにコードを取得して実行する記述の方法です。
Python関数へリクエストURLとパラメータの一致して TurboGearsCherryPyを呼び出して利用します。

tutorial/controllers.pyを開き、追記と修正を始めます。

contorollers.pyのRoot classを下のコードで置き換えたら、TurboGearsの"Hello, world!"相当のアプリケーションができます。

class Root(controllers.RootController):
    @turbogears.expose()
    def index(self):
        return "Hello, world!"

もう一度サーバをスタートさせて、ブラウザでhttp://localhost:8080へアクセスします。すると、テキストの中に"Hello, world!"が表示されます。

どうですか、動いていますか?

RootコントローラーはウェブサービスのルートURL(/)に相当します。/ のリクエストを受け取ったら、TurboGearsはRoot Controllerのiindex メソッドを見ます。indexメソッドはウェブディレクトリのindex.htmlに相当します。

publicリソース(expose)を作ります。exposeはturbogears.exposeに付随のディレクターです。*1

@turbogears.expose() 

コード内のexposedメソッドはリソースを受け取った時に実行されます。Rootコントローラにはたくさんのresourceを追加することができます。

@turbogears.expose()
def about(self):
    return "This tutorial was written by Brian Beck."

ブラウザでhttp://localhost:8080/about をアクセスしてください。

開発中はWEBサーバの再起動なしにコントローラーを作り替えることが可能です。

リクエストはパラメータも持っています。GETリクエストのURLやエンコード済みのフォームinput内のPOSTリクエストがあります。
両方のメソッドはどちらもコントローラでは同じ方法です。

@turbogears.expose()
def about(self, author="Brian Beck"):
    return "This tutorial was written by %s." % author

/aboutのリクエストではのテキストメッセージが出てきます。しかし、レスポンス /about?autor=Napoleon の表示は次のようになります。

"This tutorial was written by Napoleon."


pathコンポーネントを加えます。
resourceを含んだクラスインスタンスをRootコントローラのアトリビュートに加えます。
ここに"users"pathコンポーネントをRootコントローラへ加えます

import model

class Users:
    @turbogears.expose()
    def index(self):
        users = model.User.select()   ※ import model が必要
        return ", ".join(user.email for user in users)

class Root(controllers.RootController):
    users = Users()
    ...

/users/indexか/usresにブラウズするとデータベースの中のusersリストが表示されます。

コントローラーの構造はCherryPyのドキュメントを参照します。

http://www.cherrypy.org/wiki/CherryPyBook

いくつかのuserは自分自身のリソースをUsersコントローラの中に持っています。
しかし、この要求はデータベース内のすべてのユーザのメソッドに加えることとなる。
幸運にも、これらはダイナミックpathコンポーネントで簡単に解決できる。リソース要求があったとき、対応したコントローラーが見つけることができない。呼び出されたdefaultメソッドはリクエストリソースの名前を引数(argument)として呼び出されます。

class Users:
    ...

    @turbogears.expose()
    def default(self, userID):
        try:
            userID = int(userID)
        except ValueError:
            return "Invalid user ID!"

        try:
            user = model.User.get(userID)
        except model.SQLObjectNotFound:
            return "No such user!"
        else:
            return user.email

ブラウザで/user/1にリクエストするとID 1のユーザのe-mailアドレスが表示されるか、IDが見つからなかった場合に"No such user!"と表示されます。/users/dogをリクエストすると通常tableのIDはIntegersなので"invalid user ID!"と表示されます。

とりあえず今日はここまで。
残りは次回に続く。。。のか???

*1:from turbogears import expose を記述してると@expose()だけでよい