シリアライズと逆シリアライズ

シリアライズは、アプリケーションデータをフォームレンダリングに変換する 行為です。逆シリアライズは、フォーム送信に起因するデータをアプリケーション データに変換する行為です。

シリアライズ

シリアライズとは、 Deform に schema を与えてフォームをレンダリング するように伝えたときに行われることです。その場合に起こることの高レベルの 概略は以下の通りです:

  • アプリケーション開発者が提供した schema の中のそれぞれの schema node について、 Deform が field を生成します。 これは、スキーマ中の各ノードに対して再帰的に起こります。その結果、 スキーマ中のノードを反映してフィールドの木構造が生成されます。
  • 前のステップの結果生成されたそれぞれのフィールド・オブジェクトは、 その関連するスキーマノードのことを知っています(field.schema 属性 を持っています); それぞれのフィールドはさらに、関連する widget オブジェクトのことを知っています (field.widget 属性 を持っています)。このウィジェット・オブジェクトは、スキーマノード型に 基づいたデフォルトウィジェットかもしれません。あるいは、アプリケーション 開発者によって特定のレンダリングのためにオーバーライドされるかもしれません。
  • Deform は cstruct を得るために appstruct を root スキーマノードの serialize メソッドへ渡します。 root スキーマノードは、データ全体を単一の cstruct の中に シリアライズするために、このプロセス中で子ノードを調べることに責任を 持ちます。
  • HTML フォームレンダリングを生成するために、 Deform は得られた cstruct を root ウィジェット・オブジェクトの serialize メソッドへ渡します。 root ウィジェット・オブジェクトは、データ全体を HTML フォームにシリアライズするためにこのプロセスの間子ノードを調べる ことに責任を持ちます。

このプロセスの高レベルの概略図を作ろうとしたら、このようになるでしょう:

appstruct -> cstruct -> form
           |          |
           v          v
        schema      widget

Peppercorn 構造マーカー

デフォルトの deform ウィジェットの「シリアライズ」(フォームレンダリング) が Peppercorn 構造マーカー を使用することがわかるでしょう。

Peppercorn は Deform によって使用されるライブラリです; それは Deform が HTML フォーム送信中の form controls を名前から値へのフラットな マッピングとして扱う代わりに ストリーム として扱えるようにします。 これを実現するため、 Peppercorn は構造を表示するために hidden フォーム 要素を使用します。

Peppercorn 構造マーカーは、開始トークンと終了トークンのペアとして現れます。 例えば、与えられたフォームレンダリングの中に以下のような部分があるかも しれません:

1
2
3
4
5
6
7
8
9
  <html>
   ...
    <input type="hidden" name="__start__" value="date:mapping"/>
    <input name="day"/>
    <input name="month"/>
    <input name="year"/>
    <input type="hidden" name="__end__"/>
   ...
  </html>

上記の例は、 mapping の開始と終了の一組の peppercorn 構造マーカーの 例を示しています。この例では、逆シリアライズの間にスキーマ中の date ノードと関係するウィジェットに対して複数の値を持った辞書である pstruct が渡されるための手段としてそのペアが使用されます: 辞書にはキー day, month, year が含まれているでしょう。 また、その値は関連するフォームコントロールとやり取りした人によって 提供された値になるでしょう。

Peppercorn 構造マーカーの他の用途には次のものが含まれます: 「パスワード 確認」ウィジェットは、その中の2つのテキスト入力を持つ peppercorn マッピングを レンダリングできます。「マッピングウィジェット」は fieldset の下部構造として 使うことができます。基本的に、 Peppercorn は逆シリアライズ中にデータを フラットなマッピングからマッピング、シーケンスおよび文字列の集合に事前 変換することにより、フォーム送信データを扱いやすくします。

しかし、ウィジェットが何か手の込んだことをしようとせず、特定の ウィジェットが単一のフォームコントロールと完全に等価な場合、 そのレンダリング中に Peppercorn 構造マーカーを使用する必要は まったくありません。

Note

HTML 中で peppercorn 構造マーカーを使用することについての詳細は、 Peppercorn ドキュメンテーション を見てください。

逆シリアライズ

「逆シリアライズ」 (フォーム送信の結果得られたフォームコントロール データをアプリケーションデータに変換すること) が、どのように働くかの 高レベルの概略:

  • アプリケーション開発者が提供した schema の中の各 schema node について、 Deform が field を作成します。 これはスキーマ内のそれぞれのノードに対して再帰的に起こります。その結果、 スキーマ内のノードを反映してフィールドの木構造が作成されます。
  • 前のステップの結果として生成されたそれぞれのフィールド・オブジェクトは、 関連するスキーマノードのことを知っています (field.schema 属性を 持っています); また、それぞれのフィールドは関連する widget オブジェクトのことを知っています (field.widget 属性を持っています) 。 このウィジェット・オブジェクトは、スキーマノード型に基づいたデフォルト ウィジェットかもしれません。あるいは、アプリケーション開発者によって 特定のレンダリングのためにオーバーライドされるかもしれません。
  • Deform は cstruct を生成するために、得られた pstruct を root ウィジェットノードの deserialize メソッドに 渡します。
  • Deform は appstruct を生成するために、得られた cstruct を root スキーマノードの deserialize メソッドに 渡します。これはバリデーションエラーを生じるかもしれません。 バリデーションエラーが起きた場合、適当な場所にエラーマーカーが挿入 されたフォームがレンダリングされます。

このプロセスの高レベルの概略図を作ろうとしたら、このようになるでしょう:

formcontrols -> pstruct -> cstruct -> appstruct
             |          |          |
             v          v          v
         peppercorn   widget    schema

ユーザが任意の Deform フォーム上で submit ボタンを押した場合、 Deform それ自身は結果として生じる form controlspeppercorn.parse メソッドに渡します。これはフォームデータをマッピングに 変換します。フォームデータ中の 構造マーカー は、マッピングの内部構造 を示します。

例えば、送信されたフォームが次のデータを持っている場合:

1
2
3
4
5
6
7
8
9
  <html>
   ...
    <input type="hidden" name="__start__" value="date:mapping"/>
    <input name="day"/>
    <input name="month"/>
    <input name="year"/>
    <input type="hidden" name="__end__"/>
   ...
  </html>

pstruct マッピングの root に date キーがあり、 day, month, year の 3つのキーが含まれているでしょう:

Note

peppercorn.parse メソッドの結果と、それがフォームコントロールデータと どのように関係するかについての詳細は、 Peppercorn ドキュメンテーション を参照して ください。

ブラウザの最も「近くにある」コード片は「ウィジェット」と呼ばれます。 ウィジェットの作成に関する章はこのドキュメンテーションの 独自ウィジェットを書く に存在しています。

ウィジェットは deserialize メソッドを持っています。 deserialize メソッドには、ある構造 (pstruct) が渡されます。これは 「 Peppercorn 構造」の省略形です。 pstruct は文字列か、 マッピングか、シーケンスかもしれません。それはフォームコントロールデータ に対するスキーマノードと関係する peppercorn.parse の出力に依存します。

ウィジェットの deserialize メソッドの仕事は、受け取った pstruct を cstruct に変換することです。 cstruct は「 Colander 構造」 の省略形です。多くの場合それは文字列、マッピングあるいはシーケンスです。

アプリケーションは、いつかはモデルインスタンスや datetime オブジェクト のような文字列ほど原始的でない型を扱いたいと思うでしょう。 appstruct は、 Deform を使用するアプリケーションが最終的に扱いたい データです。したがって、ウィジェットが一旦 pstructcstruct に変換したら、そのウィジェットに関連付けられた schema node が cstruct を appstruct に変換することに責任を 持ちます。スキーマノードはそれ自身の deserialize メソッドを持っています。 それは cstruct を受け取って appstruct を返すことに責任を 持ちます。

逆シリアライズ中にエラーを送出する

ウィジェットが逆シリアライズ 中に pstruct 値を cstruct 値に正常に変換 できないと判断した場合、 colander.Invalid 例外が送出されます。

それが例外を送出する場合、フィールド・オブジェクトを他のデータを保持 するための「メモ帳」として使うことができますが、それは value 属性を 例外コンストラクタへ渡さなければなりません。例えば:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
 import colander

 def serialize(self, field, cstruct, readonly=False):
     if cstruct is colander.null:
         cstruct = ''
     confirm = getattr(field, 'confirm', '')
     template = readonly and self.readonly_template or self.template
     return field.renderer(template, field=field, cstruct=cstruct,
                           confirm=confirm, subject=self.subject,
                           confirm_subject=self.confirm_subject,
                           )

 def deserialize(self, field, pstruct):
     if pstruct is colander.null:
         return colander.null
     value = pstruct.get('value') or ''
     confirm = pstruct.get('confirm') or ''
     field.confirm = confirm
     if value != confirm:
         raise Invalid(field.schema, self.mismatch_message, value)
     return value

このウィジェットに関連したスキーマ型は、その cstruct として単一の文字列 を期待しています。逆シリアライズ中に value != confirm の場合、例外 コンストラクタに渡された value はフォームがエラーマーカー付きで 再レンダリングされるときに cstruct 値として使用されます。フォームが 再レンダリングされるときにフィールド値から confirm 値が取られます。

Say What?

Q: 「要するに deform colandar peppercorn はかなり絡み合っている (intertwingle) ってこと?」

A: 「 Colander と Peppercorn は無関係です; Deform は事実上 colander と peppercorn を統合するものです」