前章では、 input フィールドやボタンなどを含む完全なフォームをレンダリング するために Deform を使用する方法をデモンストレーションしました。そこでは deform.Field.render() メソッドを使用し、その結果として生じる HTML 断片をアプリケーションのより大きな HTML ページに埋め込みました。 これは、ページにフォームを置くための効率的で迅速な方法ですが、 フォーム HTML をレンダリングする方法に関してよりきめの細かい制御が必要 になることもあります。例えば、フォーム要素がページに水平に配置される ようにする必要があるかもしれません。あるいは Deform フォームのデフォルトの レンダリングによって使用されているフォームスタイルとは根本的に異なる フォームスタイルを必要とするかもしれません。多くの場合、 Deform をわずかに 異なるやり方で使用する方が簡単です。その場合、テンプレート内で フォームを表示するために自分でより多くの仕事をします。そして Deform の機能 のうちのいくつかだけを使用します。私たちはこれを「リテール・フォーム レンダリング」と呼びます (訳注: retail は「小売」の意味)。
Note
これは Deform 0.9.6 からの新機能です。
ここで使うスキーマとフォームオブジェクトです:
1 2 3 4 5 6 7 8 9 | import colander
class Person(colander.MappingSchema):
name = colander.SchemaNode(colander.String())
age = colander.SchemaNode(colander.Integer(),
validator=colander.Range(0, 200))
schema = Person()
form = deform.Form(schema, resource_registry=resource_registry)
|
スキーマを form 値としてテンプレートに渡します。これをするのに どんな種類のテンプレートシステムを使用するかは重要ではありませんが、 この例では ZPT を使用します。以下では、名前 form は、たった今生成した フォームを指しています:
<div class="row"
tal:repeat="field form">
<div class="span2">
${structure:field.title}
<span class="req" tal:condition="field.required">*</span>
</div>
<div class="span2">
${structure:field.serialize()}
</div>
<ul tal:condition="field.error">
<li tal:repeat="error field.error.messages()">
${structure:error}
</li>
</ul>
</div>
上記のテンプレートは、フォームのフィールドをイテレートして、 タイトルを表示するために各フィールドの属性を使用します。
すべてのフィールドをイテレートする代わりに、名前の付いたフォームフィールドを 取得するためにフォームの __getitem__ メソッドを使用することができます。 例えば:
<div tal:define="field form['name']">
<div class="span2">
${structure:field.title}
<span class="req" tal:condition="field.required">*</span>
</div>
<div class="span2">
${structure:field.serialize()}
</div>
<ul tal:condition="field.error">
<li tal:repeat="error field.error.messages()">
${structure:error}
</li>
</ul>
</div>
ウィジェットを表示するために Deform フィールド API をいくらでも使用できます。 上記の例は deform.Field.serialize() メソッドを使用します。 それは Deform にフィールド HTML を表示させる簡単な方法ですが、 もしそうしたければ、代わりに自分自身でそれを表示して、(もしあれば) その バリデーションエラーのためだけにフィールド・オブジェクトを頼ることができます。 serialize メソッドが、 Deform ウィジェットテンプレートにトップレベルの 引数として渡される任意のキーワード引数を受け取ることに注意してください。 したがって、完全に手動でやることなく特定のウィジェットがレンダリングされる 方法を変更する必要があれば、既存のウィジェットテンプレートを見て、 あなたの要求が期待されているものかどうか確かめると良いでしょう。
このフォームの POST ハンドラの中で、前章で行ったのと同様のことをします。 ただし、バリデーションが失敗した場合は単に同じフォームオブジェクトで再度 テンプレートをレンダリングします。
controls = request.POST.items() # get the form controls
try:
appstruct = form.validate(controls) # call validate
except ValidationFailure, e: # catch the exception
# .. rerender the form .. its field's .error attributes
# will be set
さらに、 “edit フォーム” を作成する deform.Form コンストラクタに appstruct 引数を渡すことも可能です。フォーム/フィールドオブジェクトは、 生成される時にこの appstruct で (再帰的に) 初期化されます。これは、 form.cstruct へのアクセスが現在のレンダリング値のセットを返すだろう ということを意味します。この値はバリデーション中にリセットされます。 したがって、バリデーションが終わった後で、バリデーションエラーを示すために 再度フォームをレンダリングすることができます。
既存の Deform ウィジェットはすべて「リテールモード」 API を使用して構築 されていることに注意してください。したがって、例が必要ならそれらの テンプレートを見ることができます。
リテールフォームレンダリングにおいて役立つかもしれないその他のメソッドは 次の通りです: