投稿日:

GAE の Model の バリデーションの動作を変えてみた


GAE のデータストアでは、値をプロパティにセットした時点で、validate されてしまう為、次のような問題があります(少なくとも僕にとっては)。

  • 複数の属性に関係するバリデーションが実現できない。
  • 入力フォームの表示用等で空のインスタンスが欲しい時、インスタンス化された時点で validate されるので利用できない。

これらの回避の為に、バリデーション周りを以下のようにして変えてみました。

 

以下、簡単な解説です。

  • setattr(db.Property, ‘__set__’,……
    今回のキモ。db.Property クラスの __set__ デスクリプタ メソッドを上書きし、属性代入時のバリデーションをバイパスしています。GAE v1.2.6 において、Property の定義済み実装クラス群では、ReferenceProperty 以外は __set__ のオーバーライドがありません。ReferenceProperty は __set__ がオーバーライドされていますが、目的に対しては特に影響無いものでしたので、属性保存時のバリデーションの無効化は、とりあえずこれで OK!
  • BaseModel クラス
    GAE の db.Model をサブクラスを作成し validate メソッドを追加しています。validate メソッドは、Model インスタンスの全ての属性をバリデーションし、検出されたエラーを、errors に保存します。アプリケーションの Model は、この BaseModel を継承して作成し、保存の前には必ず、validate()(または is_valid)を呼んでください。
  • Errors/Error クラス
    エラー情報を処理するコンテナ。

 

以下のように利用します。

 

…とまあ、こんな感じです。

注意点として、Rails のように、put() などで自動的に validate はされません。必ず、is_valid の参照、または validate() の呼び出しが必要です。実装するのは簡単ですが、これぐらいで不便は無いと思うし、GAE 側の Model の今後の変更にもやや強いかと思っています。

…次はバリデーション エラーメッセージの日本語化ですね…。