[TurboGears] ブログを作成する。その4

注意

この記事は、id:SumiTomohiko:20070118:1169099368の続きです。

その3からの変更点

id:SumiTomohiko:20070118:1169099368のあと、画面のデザインを変更し、記事を編集、削除する機能を追加しました。現在は、以下のような画面になっています。

デザインの変更や、編集、削除の処理自体はたいしたことはないので、説明は省略します。この記事では、ウィジェットを使ったところについて説明します。

ウィジェット

ウィジェットは、ビューの部品です。複数の箇所に存在する同じ部品を、共通化することができます。今回は、記事の登録画面と編集画面にある、記事を入力する以下のフォームを、ウィジェットで共通化します。

ウィジェットは、TurboGears Widget Browserでみることができます。TurboGears Widget Browserは、tg-admin toolboxコマンドを実行した後、http://127.0.0.1:7654/をブラウザで開き、メニューの左下にある"Widget Browser"をクリックすると閲覧できます。TurboGears Widget Browserには様々なウィジェットがありますが、その中のTable Formがもっともイメージに近いので、これを継承して作ることにします。

修正するファイルは、tgdiary/controller.pyです。まず、turbogears.widgetsをimportします。

from turbogears import controllers, expose, widgets

次に、フォームを表すウィジェットを作成します。turbogears.widgets.TableFormを継承します。記事登録画面と編集画面ではフォームを送信するURLが異なるので、コンストラクタのaction変数に送信先を渡すようにします。

class ArticleFormWidget(widgets.TableForm):
    def __init__(self, action):
        title_field = widgets.TextField('title', label=u'題名', attrs=dict(size='64'))
        body_field = widgets.TextArea('body', label=u'本文', rows=16, cols=64)
        super(ArticleFormWidget, self).__init__('ArticleEditForm', fields=[title_field, body_field], action=action, submit_text=u'送信')

コンストラクタでは最初に、フォームに設置するテキストボックスとテキストエリアを作成します。

テキストボックスを表すクラスは、turbogears.widgets.TextFieldです。TextFieldのコンストラクタの最初の引数は、<input>タグのname属性の値です。これはまた、ウィジェットを表示するときに与えられたオブジェクトの、表示する属性を表します(後述します)。label引数は、テキストボックスの左に表示される文字列です。label引数がない場合は、最初の引数がそのまま表示されます。attrs引数は、それ以外の属性を辞書で与えます。ここでは、size属性を設定しています。

テキストエリアを表すクラスは、turbogears.widgets.TextAreaです。TextFieldと同様に、最初の引数はname属性の値であり、label引数は横に表示される文字列です。rows引数とcols引数は、<textarea>タグのrows属性とcols属性に対応します。

なお、どんなウィジェットがどんなパラメータをとるかは、TurboGears Widget Browserで閲覧できます。

コンストラクタの最後では、親クラス (TableForm) のコンストラクタを呼び出します。<form>タグのname属性の値と、フォームに含まれるTextFieldとTextArea, フォームのaction属性の値、送信ボタンの表示文字列を設定します。

ウィジェットを使うときは、まずコントローラ内でウィジェットを作成します。例えば、記事の編集画面を表示するeditメソッドでは、以下のようになります。上述の通り、コンストラクタにはフォームの送信先URLを与えています。ウィジェットはビューで使用するので、メソッドの戻り値の辞書に含めます。

    @expose(template="tgdiary.templates.edit")
    @identity.require(identity.not_anonymous())
    def edit(self, id):
        # TODO: Validate id and user's id.
        article = Article.get(id)
        article_form_widget = ArticleFormWidget('/doedit?id=%s' % id)
        return dict(article=article, article_form_widget=article_form_widget)

ウィジェットを使うtgdiary/templates/edit.kidでは、以下のように記述します。

                ${article_form_widget.display(article)}

ウィジェットのオブジェクトのdisplayメソッドを呼び出すだけです。displayメソッドには、ウィジェットで表示するオブジェクトを与えます。このオブジェクトの、TextFieldオブジェクトなどのコンストラクタで指定した属性が、各フィールドに表示されます。

参考文献

id:aodag:20070114:1168796301