WidgetsのTableFormと、「**」表記について

WidgetsのTableFormは、複数のWidgetを詰め込んでフォームにできる。詰め込むのはもちろんINPUT要素になるようなWidgetで、たとえば以下のように書ける。(書いてる本からの抜粋)

from turbogears import widgets

class EditUserWidgets(widgets.WidgetsList):
    user_name = widgets.TextField(name="user_name", label=u"ログイン名")
    display_name = widgets.TextField(name="display_name", label=u"ユーザー名(表示用)")
    password = widgets.PasswordField(name="password", label=u"パスワード")
    email_address = widgets.TextField(name="email_address", label=u"メールアドレス")
    modify = widgets.CheckBox(name="modify", label=u"利用者")
    id = widgets.HiddenField(name="id")

edit_user_form = widgets.TableForm(fields=EditUserWidgets(), submit_text=u"登録")

こうやって作成したTableFormのインスタンスに対して、display()を読んでやると、Elementが得られる。これは実際にテンプレート上で(X)HTMLに展開されるオブジェクトである。

edit_user_form.display(action='edituser')
  または
edit_user_form(action='edituser')

さて、edit_user_formはフォームの「型」の定義で、HTMLに展開するのはフォームの「インスタンス」という対応になる。なので、インスタンスに対して追加の設定をしたい場合がある。初期値を入れたいとか、(ある条件下で)一部の項目をreadonlyにしたいとか、(エラーがあった項目の)ラベルの色を変えたい、などだ。

フォームの中身であるTextFieldに対しては、valueやattrsなどの引数を渡すと、設定ができる。次のような感じ。

f = TextField(name='input1', label=u'入力1')
f.display(value=u'入力してください', 
          attrs={'readonly':True}, 
          field_class='warning')

display()の呼び出し時に、いくつかの設定を追加している。これは「入力1という要素の『型』を、インスタンス化するときの設定」になる。フォームをインスタンス化するときに、内部では各(Widgetの)要素をインスタンス化するので、上記のような設定を渡したい。

どうするかと言うと、「フォームのdisplay()に対して、中身の要素に渡したいのと同じ名前付き引数に、nameをキーとした辞書を渡すと、指定したnameの要素に辞書の中身が渡る」という仕組みを利用する。上のTextFieldの例を設定するなら、次のようになる。

edit_user_form.display(value={'input1':u'入力してください'},
                       attrs={'input1':{'readonly':True}},
                       field_class={'input1':'warning'})

もちろん、複数の項目に設定するときは、それぞれのnameをキーにして辞書に追加してやればよい。やりかたを知ってしまうと、とても直感的で便利だ。