テンプレート

フォームレンダリングの見た目をカスタマイズしやすくするために、 Chameleon テンプレートのセットが deform の中に存在する デフォルトウィジェットセットによって使用されます。

デフォルトテンプレートをオーバーライドする

デフォルトウィジェットは deform パッケージの templates ディレクトリにあるテンプレートを使用します。 Chameleon テンプレート システムを使用することに満足していて、これらのテンプレートのうちの いくつかだけをオーバーライドする必要がある場合、自分のテンプレート ディレクトリを作成して、カスタマイズしたいテンプレートをそこにコピー することができます。そして、新しいテンプレートディレクトリをすべての フォームで使用するように設定するか、あるいは下記に述べられているように 特定のフォームだけで使用することができます。

適切な API ドキュメンテーションのために deform.ZPTRendererFactory クラスおよび deform.Field クラスの renderer 引数を見てください。

すべてのフォームでオーバーライドする

テンプレートを全体的にオーバーライドするには、デフォルト ZPT レンダラー に関連した設定を変更する deform.Field.set_zpt_renderer() クラスメソッドを使用してください:

from pkg_resources import resource_filename
from deform import Form

deform_templates = resource_filename('deform', 'templates')
search_path = ('/path/to/my/templates', deform_templates)

Form.set_zpt_renderer(search_path)

これによって、フォームがレンダリングされる場合は常に /path/to/my/templates にあるテンプレートがデフォルトテンプレート より優先して使用されるようになります。検索パスには任意の数のテンプレート ディレクトリを入れることができます。それらは順に検索されて、最初に 見つかったテンプレートが使われます。

特定のフォームでオーバーライドする

特定のフォームだけで、あるいはフォームの特定のレンダリングだけで 使用されるテンプレートを変更したい場合は、 deform.Form コンストラクタに renderer 引数を渡すことができます、例えば:

from deform import ZPTRendererFactory
from deform import Form
from pkg_resources import resource_filename

deform_templates = resource_filename('deform', 'templates')
search_path = ('/path/to/my/templates', deform_templates)
renderer = ZPTRendererFactory(search_path)

form = Form(someschema, renderer=renderer)

上記のフォームがレンダリングされる時に、 /path/to/my/templates に あるテンプレートがデフォルトテンプレートより優先して使用されます。 検索パスには任意の数のテンプレートディレクトリを入れることができます。 それらは順に検索されて、最初に見つかったテンプレートが使われます。

別のテンプレートシステムを使う

renderer は、 deform の各ウィジェット実装によってテンプレートの セットから HTML をレンダリングするために使用されます。デフォルトでは、 デフォルト Deform ウィジェットのそれぞれは Chameleon ZPT テンプレート 言語で書かれたテンプレートを使用します。ウィジェットで異なるテンプレート システムを使用したければ、それは可能です。そのためには次のことが必要です:

  • 好みのテンプレートシステムを使用する代替レンダラーを書く。
  • 任意で、既存のすべての Deform テンプレートを選択したテンプレート言語 に変換する。これは、 Deform の一部として付属しているウィジェットを 使用することを選んだ場合にのみ必要です。
  • deform.Form クラスのデフォルトレンダラーをセットする。

レンダラーを作成する

レンダラーは、単に1つの位置引数 (テンプレート名) とキーワード引数を 受け取る callable です。レンダラーが受け取るキーワード引数は任意で、 ウィジェット毎に異なります。しかし、キーワードは通常 field (field オブジェクト) と cstruct (テンプレート自身によって レンダリングしなければならない、フィールドと関係するデータ構造) を 含んでいます。

これは、 Mako テンプレートエンジンを使用する (素朴な) レンダラーの例です:

1
2
3
4
5
from mako.template import Template

def mako_renderer(tmpl_name, **kw):
    template = Template(filename='/template_dir/%s.mak' % tmpl_name)
    return template.render(**kw)

Note

より頑健な実装では、なんらかのキャッシュを行うテンプレートローダーを 使用したり、テンプレートディレクトリが設定可能になっていたりする かもしれません。

作成した mako_renderer 関数が、実際は渡された tmpl_name.mak 拡張子を追加していることに注意してください。これは、異なる テンプレートシステムをレンダラーとして使用することができるように、 Deform が拡張子のないテンプレート名を渡すからです。

mako_renderer レンダラーは、すでにテンプレートを作り始めることが できる状態になっています。

デフォルトの Deform テンプレートを変換する

deform パッケージには templates という名前のディレクトリが 含まれています。 ソースリポジトリのブラウジング によって、 このディレクトリの現在の trunk の内容を見ることができます。このディレクトリと サブディレクトリの中にあるファイルはどれも、デフォルト Deform ウィジェットに よって使用される Chameleon ZPT テンプレートです。

例えば textinput.pt ZPT テンプレートはこのようになります (それは deform.widget.TextInputWidget ウィジェットによって使用され、 テキスト入力コントロールをレンダリングします):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<span tal:define="name name|field.name;
                  size size|field.widget.size;
                  css_class css_class|field.widget.css_class;
                  oid oid|field.oid;
                  mask mask|field.widget.mask;
                  mask_placeholder mask_placeholder|field.widget.mask_placeholder;
                  style style|field.widget.style|None;
"
      tal:omit-tag="">
    <input type="text" name="${name}" value="${cstruct}" 
           tal:attributes="size size;
                           class css_class;
                           style style"
           id="${oid}"/>
    <script tal:condition="mask" type="text/javascript">
      deform.addCallback(
         '${oid}',
         function (oid) {
            $("#" + oid).mask("${mask}", 
                 {placeholder:"${mask_placeholder}"});
         });
    </script>
</span>

もし Mako レンダラーを作成していれば、このテンプレートの類似物を作成する 必要があるでしょう。それは textinput.mak と命名されるべきで、 このようになります:

1
2
3
4
5
<input type="text" name="${field.name}" value="${cstruct}"
% if field.widget.size:
size=${field.widget.size}
% endif
/>

テンプレートの本体が何であっても、結果として得られる textinput.mak は Deform によって使われる他の Mako テンプレートファイルを格納するための ディレクトリに置かれるべきです。 Deform の templates ディレクトリと そのサブディレクトリに存在するテンプレートそれぞれを変換する必要が あるでしょう。また、結果として得られるすべてのテンプレートを、ディレクトリ 構造も保持したままプライベートの mako templates ディレクトリに入れる 必要があるでしょう (例えば readonly ディレクトリがあるという事実を 保持しながらその内容を変換する)。

新しいレンダラーをデフォルトに設定する

新しいレンダラーを作成して既存のすべての Deform テンプレートに対応する テンプレートを作成したら、そのレンダラーが Deform によって使用されるように 設定することができます。初期化コードに以下のようなコードを追加してください:

1
2
3
4
from mymakorenderer import mako_renderer

from deform import Form
Form.set_default_renderer(mako_renderer)

これで、 deform ウィジェットシステムは、デフォルトレンダラーとしてあなたの レンダラーを使用するようになります。

deform.Field.set_default_renderer() を呼び出すと、それを起動した 同一プロセス内のすべての場所で、このレンダラーがデフォルトとして 使われるようになることに注意してください。これは潜在的に望ましくありません: たとえば同じプロセスが Deform を使用する 2 つの異なるシステムを収容 しているといった理由で、同一プロセスで複数のレンダラーを使用する必要 があるかもしれません。この場合、 set_default_renderer メソッドを 使用する代わりに、アプリケーションが Form コンストラクタにレンダラーを 渡すように書くことができます:

1
2
3
4
5
6
from mymakorenderer import mako_renderer
from deform import Form

...
schema = SomeSchema()
form = Form(schema, renderer=mako_renderer)