TurboGearsでメモ帳アプリを作る 2

前回までで「新規作成画面」を作ったので、次はそこから[追加]ボタンをクリックされたらフォームに入力された内容でテキストファイルを作る処理を実装する。

「pynote/controllers.py」を開く。「新規作成画面」のフォームに割り当てられたアクション(URL)は「add」なので、これと同じ名前のメソッドをコントローラクラスに作る。

pynote/controllers.py
from turbogears import redirect
# テキストファイルを保存するディレクトリ
contents_dir = "contents/"

class Root(controllers.RootController):
    # 省略...
    
    @expose()
    def add(self, name, text):
        f = open(contents_dir + name, "w")
        f.write(text)
        f.close()
        
        flash(u"「%s」 を追加しました。" % name)
        return redirect("index")

今回は画面を表示するわけではないのでexposeデコレータにはテンプレートを指定しない。
引数として、「name」と「text」を定義する。これらの引数には「新規作成画面」からPOSTされた同じ名前のデータが自動的にマッピングされて、値が渡されてくる。これは便利!ここにはURLに渡されたクエリ文字列も渡されてくる。

処理自体はテキストファイルを作って、内容を書き込むだけ。あとは「flash」メソッドで画面上部にメッセージを表示することができるので、追加した旨のメッセージを表示して、「redirect」メソッドで「メイン画面に」リダイレクトしている。

ためしに「新規作成画面」で適当なデータを入力して[追加]ボタンをクリックすると、以下のように「メイン画面」に遷移されて、画面上部にメッセージが表示される。

こんな感じで簡単にファイルを追加できたわけだけど、これでは何も入力しないで[追加]ボタンをクリックした時にはもちろんエラーになってしまう。なので[追加]ボタンをクリックされた時に入力チェックを行う必要があるんだけど、TurboGearsではこの入力値検証を行う機能が標準で用意されている。

それを使うのも非常に簡単で入力値検証をしたいメソッドにデコレータ関数を適用するだけ。

pynote/controllers.py
from turbogears import validators
import turbogears

class Root(controllers.RootController):
    # 省略...

    @expose()
    @turbogears.error_handler(new)
    @turbogears.validate(form=nform,
        validators=dict(name=validators.NotEmpty(), text=validators.NotEmpty()))
    def add(self, name, text):
        f = open(contents_dir + name, "w")
        f.write(text)
        f.close()

        flash(u"「%s」 を追加しました。" % name)
        return redirect("index")

「add」メソッドにまずturbogears.error_handlerデコレータでエラーが出た場合に、どの画面に遷移するかを指定する。ここではエラーが出れば「新規作成画面」に遷移して、エラー内容を表示する。

次にturbogears.validateデコレータで検証の種類を指定する。「form」引数で検証する入力フォームを指定する必要があるけど、現状では「new」メソッドの内部で入力フォーム「nform」を生成して返しているだけなので、デコレータから参照できない。なのでこの入力フォームをコントローラクラスの外部に出して、それを参照するようにする。

nform = PyNoteForm(
    action="add",
    submit_text=u"追加",
    fields=[
        widgets.TextField("name", u"ファイル名"),
        widgets.TextArea("text", u"内容")
    ])

class Root(controllers.RootController):
    # 省略...
    
    @expose(template="pynote.templates.new")
    def new(self):
        return dict(nform=nform)
        
    # 省略...

あとは「validators」引数にディクショナリで検証する引数名と検証の種類をキーペアにして渡す。ここでは必須項目チェックのvalidators.NotEmptyを使っている。(他にもいろんな種類がある)

これで「新規作成画面」で何も入力せずに[追加]ボタンをクリックすると、以下のようにエラーメッセージが表示される。