読者です 読者をやめる 読者になる 読者になる

SQLAlchemyのバリデーションフレームワークを作った

PythonのORMであるSQLAlchemyのバリデーションフレームワークを以前作ったのでその紹介。

https://pypi.python.org/pypi?%3Aaction=pkg_edit&name=sqlalchemy_validation

github.com

作ったものの拡張性とか柔軟性に欠けるかなと反省している。

経緯

tornadoとsqlalchemyを使ってWebアプリを作っていたのだが、 sqlalchemyにはモデル定義に基づいてバリデーションをする機能はなく、 integer型のフィールドにもstr型の値を入れられたりする。 各フィールドごとに独自のバリデーション関数を定義する機構はあるが、 基本的な型チェックや字数チェックはわざわざ個別に実装しなくても モデル定義に基づいて自動でやってほしいと思った。

そういったライブラリを軽く探したが、何故か良さげなものがなかったので自分で作った。

特徴

サポートしているバリデーション項目は

である。

sqlalchemy標準のクラスを継承して拡張しており、 通常のコードをほとんど修正せずにバリデーション機能を実装できる。

モデルインスタンスのコンストラクタ呼び出し及び属性への値の代入時に バリデーションが実行され、バリデーションに引っかかったら例外を投げるようになっている。

例外クラスは例外の種類に応じて定義してあり、 例外には例外処理時に必要十分なデータをもたせるようにしている。

複数のフィールドに同時に値をセットする場合、 複数の例外を保持出来る専用の例外を投げることで 複数のバリデーションエラーも扱えるようにしている。

ただし、場合によっては一つのフィールドで例外が起こったら それ以降のバリデーション処理を止めて即座に例外を投げてほしい場合もあるので、 そういったニーズにも答えられるようなヘルパー関数を提供している。

SQLAlchemyのようなORMのモデルクラスのフィールドの名前空間は 基本ユーザが自由に使うものであるので、このフレームワークで勝手にメソッドを定義したりはしないようにした。 例えば、モデルクラスにvalidateメソッドを勝手に定義するようなことはせず、 validate関数を別に提供している。

問題点

バリデーションの実行タイミングを選べない

モデルインスタンスのコンストラクタ呼び出し及び属性への値の代入時にバリデーションが実行されるため、 ユーザが明示的にバリデーションを実行する必要はない。 これは良く言えば親切だが、悪く言えばおせっかいであり、余計ともいえる。

自動実行はON/OFFで切り替えられるべきだったなと思う。

バリデーション項目をユーザが自由に拡張できない

最後に

自分が作ったものを紹介する意味で記事書いたけど、 半年以上前に作ったものだからよく覚えていなかった。