Cerberus入門!ばりばりバリデーションしよう!

f:id:kai1233:20181218224628p:plain

この記事は BeProud Advent Calendar 2018 - Adventar の18日目の記事です。

Cerberus とは

ケルベロスとは本来、ギリシャ神話の地獄の神ハーデスのペットのわんわんであり、地獄の入り口にいる番犬のことだそうです。Cerberus はその名の通り、番犬のようにユーザからのリクエストにバリデーションをかけて不正なリクエストを弾いてくれるPythonのライブラリです。公式ページいわく、パワフルでありながらもシンプルで軽量なバリデーションライブラリだそうです。しかも簡単に拡張することができるそうです。いま仕事で使う機会があり、少しずつ使い方を覚えています。せっかくなので今回基本的な機能をやさしくまとめてみようと思います。

バリデーションしてみる

まずはCerberusをインストールしましょう。pipを使えば簡単にインストールできます。

pip install cerberus

Cerberusをインストールしたら対話モードでバリデーションしてみます。以下の様に簡単にバリデーションを試してみることができます。

>>> from cerberus import Validator
>>> schema = {'company': {'type': 'string'}}
>>> v = Validator(schema)
>>> document = {'company': 'BeProud'}
>>> v.validate(document)
True

schemaでどのようなデータを受け取るかを指定しています。上に書いた例だとschema = {'company': {'type': 'string'}} という風に定義しています。companyという名前のデータをstring型の場合のみ受け取るという定義になっています。見ての通り、schemaは辞書型で定義します。

そしてv = Validator(schema)で定義したschemaを引数として与えschemaをバリデータに反映させます。

次はバリデータをテストしてみるデータを作ります。document = {'company': 'BeProud'}のように、定義したschemaに合う辞書型のデータを変数に代入します。v.validate(document)のように実行すると、今回は定義したとおりcompanystring型のデータが入っているのでバリデーションが通りTrueが返ってきます。

当たり前ですがint型のデータをcompnayに代入してバリデーションをかけるとFalseが返ってきます。

>>> document = {'company': 1}
>>> v.validate(document)
False

ちゃんと期待通りに動いてくれていますね。ありがとうございます。

Schemaで定義できるいろいろ

Schemaで定義できる便利なやつをまとめます。

デフォルトで用意されているいろいろ

  • required: True 必須データ データが必須かどうかを指定できます。必須データが存在しないばあいは以下のようにFalseを返します。
>>> schema = {'company': {'type': 'string'}, 
                           'name': {'type': 'string', 'required': True}}
>>> v = Validator(schema)
>>> v.validate({'company': 'BeProud'})
False

正規表現を使って柔軟なバリデーションを行うこともできます。

>>> schema = {'company': {'type': 'string', 'regex': r'^B.*?$'}}
>>> v = Validator(schema)
>>> v.validate({'company': 'BeProud'})
True
>>> v.validate({'company': 'AeProud'})
False
  • coerce: '型名' 型の変換

coerceを使うことでバリデーションするデータを任意の型に変換することができます。変換できない場合はバリデーションエラーとなります。

# integerのschemaにstr型の’1’を与える
>>> schema = {'age': {'type': 'integer'}}
>>> v = Validator(schema)
>>> v.validate({'age': '1'})
# 当たり前ですがFalseが返ってくる
False

# coerceでint型を指定して型変換を行う
>>> schema = {'age': {'type': 'integer', 'coerce': int}}
>>> v = Validator(schema)
>>> v.validate({'age': '1'})
# str型からint型へ型変換が行われてバリデーションが通る
True

自分で用意できるいろいろ

  • カスタムルール

Cerberusでは自分で新たにSchemaに定義できるルールを新たに追加することができます。たとえば、好きな色(fav_color)というバリデーションのルールを作ってみましょう。僕は赤が好きなのでRed以外のcolorのデータが送られてきたらエラーを返すようになっています。

>>> from cerberus import Validator
>>> schema = {'color': {'fav_color': True, 'type': 'string'}}
>>> class MyValidator(Validator):
>>>    def _validate_fav_color(self, fav_color, field, value):
>>>        if fav_color and value is not 'Red':
>>>            self._error(field, "My favorite color is Red :/")

>>> v = MyValidator(schema)
>>> v.validate({'color': 'Blue'})
>>> False
>>> v.errors
>>> {'color': ['My favorite color is Red :/']}

>>> v.validate({'color': 'Red'})
>>> True
>>> v.errors
>>> {}
  • カスタムデフォルトセッター 特定の値にデータが存在しない場合に、代入するデフォルトの値を与えることができます。colorのデフォルトの値を僕の好きなRedにします。
>>> from cerberus import Validator
>>> class MyNormalizer(Validator):
>>>    def _normalize_default_setter_fav_color(self, document):
>>>        return 'Red'

>>> schema = {'color': {'type': 'string', 'default_setter': 'fav_color'}}
>>> MyNormalizer().normalized({}, schema)
>>> {'color': 'Red'}

空の辞書データを.normalized()すると無事{'color': 'Red'}が返ってきました。デフォルトの値がちゃんと設定できていますね。

まとめ

ほかにもたくさんのデフォルトの設定や、カスタムができますがここでは紹介しきれないので気になる方はぜひCerberosの公式ページへGo!また少しずつ調べて追記していきま〜す!