Pythonで 値のバリデーションを行う時に便利なライブラリ「schematics」の紹介です。
Webサイトのフォームでは ログイン時など、コマンドラインアプリでは必要なパラメーター ( 引数 ) があるかどうか など、データを受け取る場面では 必ず値の整合性を確認します。
だいたいのことは 下記のスニペットのように ' if
' 文を使って確認すれば問題ありませんが、受け取るデータが多いと 制御文のネストや、コードが長くなったりして 当然ながら可視性が悪くなります。
data = {
'field1': 'field1 val', # required
'field2': 'field2 val', # required
'customField1' : 'custom val1',
'customField2' : 'custom val2'
# ...
}
# 値が空白ではないかチェック
if not data['field1'] == '' and not data['field2'] == '':
# .....
pass
そのようなバリデーションが Pythonで 必要な時に便利に使えそうなライブラリが「schematics
」です。
- バリデーション専用の データ構造クラス を定義して、楽に値の整合性が確認ができる
schematicsのインストールは ' pip
' コマンドを使っておこないます。なお、サポートされている Pythonのバージョンは、 2系が ' 2.7.*
'、 3系が ' 3.3 ~ 3.6
'です。
# pipコマンドを使ってインストール
pip install schematics
schematics は バリデーション用の 構造モデルを作成して使用します。
Djangoなどの MVCフレームワークにも同様の物が見られますが、 データベース用の Model作成時にテーブルのスキーマを定義するのと コンセプトは同じです。
下のスニペットは ' schematics ' を使って、ユーザー追加時の バリデーションのモデル、 ' UserCreate ' クラスを 作成しました。
# validations/user.py
"""
クラス内のプロパティが判定する値のKeyとなります。全てのフィールドに適切な型 ( タイプ ) を指定。
また、' require ' などのオプションを使ってデータに制限を割り当てています。
"""
from schematics.models import Model # バリデーション用のモデル
# バリデーション用の型判定用のライブラリ
from schematics.types import StringType, URLType, EmailType
# ユーザー作成用のバリデーションモデル
class UserCreate(Model):
# ここのデータ構造(変数)を定義していく
name = StringType(required=True, min_length=5, max_length=20) # Stringタイプ
email = EmailType(required=True) # Emailタイプ
password = StringType(required=True, min_length=8) # Stringタイプ
続いて、下のスニペットが 上記で作成した ' UserCreate ' クラスの利用方法です。
クラスをインスタンス化した後、クラスのプロパティと元となるデータを合致させ ' * validate()
' メソッドを使って値が正しい構造かどうか判定します。
( * 値が定義した場合の構造通りの場合は ' None
' を、そうでない場合は ' DataError
' が返ってきます )
# app.py
from validations.user import UserCreate # UserCreateクラスのインポート
# 判定するデータ
data = {
"name" : "myUserAccount",
# "email" : "test@example.email",
"email" : "testexample.email", # E-mailですが意図的に値を変更
"password" : "12345679abc"
}
# バリデーション用のUserCreateクラスをインスタンス化
user = UserCreate()
# 値の割り当て #
user.name = data["name"]
user.email = data["email"]
user.password = data["password"]
# 値の判定
user.validate()
# user.emailがe-mailフォーマットではないので、下記のエクセプションが発生
# schematics.exceptions.DataError: {"email": ["Not a well-formed email address."]}
# .to_primitive() メソッドでモデルに割り当てた値を取り出すことができます
# user.to_primitive()
schematics には 値の構造を定義する為に 様々な タイプ ( 型 ) が用意されています。
モデルのプロパティに タイプ( 型 )を 指定することで適用できます。
from schematics.models import Model
# Stringタイプと URLタイプをインポート
from schematics.types import StringType, URLType
class Person(ValidationModel):
# インポートした StringTypeを適応
name = StringType(required=True)
password = StringType(required=True, min_length=5)
website = URLType()
- 日付 ( Number )
DateType, DateTimeType, TimestampType, UTCDateTimeType
- 数値
IntType, LongType, NumberTypem DecimalType, FloatType,
- 文字列 ( String )
MultilingualStringType, StringType
- 真偽 ( Bool )
BooleanType
- ハッシュ文字列
MD5Type, UUIDType, SHA1Type
- 配列
ListType, DictType
- その他
GeoPointType,
IPv6Type, IPv4Type, IPAdress(v4, v6): IP アドレス
EmailType, MACAddressType, URLType,
- Schematics 固有のタイプ
ModelType, PolyModelType
Schematics : 用意されているタイプ ( 型 )
バリデーションをおこなう上で、型(タイプ) 以外にも様々な判定が必要になる場合は 多々あります。例えば、画像を変換するコマンドラインアプリで引数で画像ファイルを受け取る際の 特定の拡張子のみ許可など。
そのような時の為に schematics では、 自作のメソッドをカスタムエクセプションとして、モデルに組み込むことができます。
下の例では、 文字列が ' .jpeg ' で終わっているか判定する 自作メソッドを追加してみました。
from schematics.models import Model
from schematics.types import StringType, URLType
# error用のモジュール
from schematics.exceptions import ValidationError
# 値が '.jpeg' で終わるか判定するメソッド
def is_endswithJpeg(value):
if not value.endswith('.jpeg'):
# エラーメッセージ
raise ValidationError(u'Please end with .jpeg')
return value
class Person(Model):
name = StringType(required=True)
password = StringType(required=True, min_length=5)
website = URLType()
# validatorsオプションの配列内にカスタムメソッドを追加
img = StringType(validators=[is_endswithJpeg]) # is_endswithJpegの適応
以上が schematicsの紹介でした。schematicsには上で紹介した事以外にも沢山の機能が用意されています。Pythonのバージョンも幅広くサポートされているので、既存のプロジェクトでも簡単に使用することができます。
schematics を使ってバリデーション用のモデルと作成すると、送られてくるデータを一元管理し易すくなったり、ある場面では if文などの条件式を減らすことが出来そうです。