Skip to content

Instantly share code, notes, and snippets.

@terukizm
Last active November 28, 2016 13:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save terukizm/7cb8d2be50638a91665edcacb085b58d to your computer and use it in GitHub Desktop.
Save terukizm/7cb8d2be50638a91665edcacb085b58d to your computer and use it in GitHub Desktop.
Pythonの汎用データバリデーションライブラリ「Cerberus」を使う ref: http://qiita.com/terukizm/items/db8a70158e94525c69d5
$ pip install cerberus
False
{'mail_address': ["指定された'tanaka_at_test.com'は、メールアドレスとして不正です。"]}
schema = {
'mail_address' : {
'exists_keyword' : 'SUZUKI',
},
}
# -*- coding: utf-8 -*-
import re
from pprint import pprint
from cerberus import Validator
class CustomValidator(Validator):
# [Custom Rules]
# http://docs.python-cerberus.org/en/stable/customize.html#custom-rules
def _validate_exists_keyword(self, exists_keyword, field, value):
"""
※以下のdocstringを書かないとwaringが出る
The rule's arguments are validated against this schema: {'type': 'string'}
"""
if value.find(exists_keyword) < 0:
self._error(field, "与えられた文字列'%s'の中に、キーワード文字列'%s'が存在しませんでした。" % (value, exists_keyword))
schema = {
'mail_address' : {
'exists_keyword' : 'SUZUKI',
},
}
data = {
'mail_address' : 'tanaka_at_test.com',
}
v = CustomValidator(schema)
pprint(v.validate(data))
pprint(v.errors)
False
{'mail_address': ["与えられた文字列'tanaka_at_test.com'の中に、キーワード文字列'SUZUKI'が存在しませんでした。"]}
# ×NG
schema = {
'mail_address' : {
'has_bad_word', # dict形式になっていない
},
}
# ◯OK
schema = {
'mail_address' : {
'has_bad_word' : True, # docstringで{'type': 'boolean'} 指定
},
}
-----------------------------------------
◯OK
-----------------------------------------
True
{}
-----------------------------------------
×NG
-----------------------------------------
False
{'age': ['min value is 0'],
'birthday': ['must be of date type'],
'email': ['required field'],
'name': ['empty values not allowed'],
'phones': [{0: ['value does not match regex '
"'^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$'"],
1: ['value does not match regex '
"'^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$'"]}],
'sex': ['unknown field']}
# -*- coding: utf-8 -*-
from pprint import pprint
from cerberus import Validator
from cerberus.errors import BasicErrorHandler
class CustomErrorHandler(BasicErrorHandler):
""" BasicErrorHandler.message を上書きして日本語化 """
def __init__(self, tree=None):
super(CustomErrorHandler, self).__init__(tree)
# 文言を適宜日本語化してください
self.messages = {
0x00: "{0}",
0x01: "document is missing",
0x02: "required field",
0x03: "知らない項目 '{field}' です",
# ... (略) ...
0x93: "no definitions validate",
0x94: "one or more definitions don't validate"
}
schema = {
'mail_address' : {'type' : 'string'},
}
data = {
'name': '田中', # 0x03: バリデーションエラー
'mail_address' : 'tanaka_at_test.com',
}
# 拡張したBasicErrorHandlerを指定
v = Validator(schema, error_handler=CustomErrorHandler())
pprint(v.validate(data))
pprint(v.errors)
False
{'name': ["知らない項目 'name' です"]}
schema = {
'mail_address' : {
'type' : 'email',
},
}
# -*- coding: utf-8 -*-
import re
from pprint import pprint
from cerberus import Validator
REGEX_EMAIL = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
class CustomValidator(Validator):
# [Custom input_data Types]
# http://docs.python-cerberus.org/en/stable/customize.html#custom-input_data-types
def _validate_type_email(self, value):
if re.match(REGEX_EMAIL, value):
return True
schema = {
'mail_address' : {
'type' : 'email',
},
}
data = {
'mail_address' : 'tanaka_at_test.com',
}
v = CustomValidator(schema)
pprint(v.validate(data))
pprint(v.errors)
False
{'mail_address': ['must be of email type']}
schema = {
'mail_address' : {
'validator': check_mail, # ←check_mail() メソッド
},
}
# -*- coding: utf-8 -*-
import re
from pprint import pprint
from cerberus import Validator
REGEX_EMAIL = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
# [Custom Validator]
# @see http://docs.python-cerberus.org/en/stable/validation-rules.html#validator]
def check_mail(field, value, error):
if not re.match(REGEX_EMAIL, value):
msg = "指定された'%s'は、メールアドレスとして不正です。" % value
error(field, msg)
schema = {
'mail_address' : {
'validator': check_mail, # ←check_mail() メソッド
},
}
data = {
'mail_address' : 'tanaka_at_test.com',
}
v = Validator(schema)
pprint(v.validate(data))
pprint(v.errors)
# -*- coding: utf-8 -*-
from cerberus import Validator
import re
from datetime import datetime, date
from pprint import pprint
# バリデーション定義
schema = {
'name': {
'type': 'string',
'required': True,
'empty': False,
},
'email': {
'type': 'string',
'required': True,
'regex': '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$',
},
'age': {
'type': 'integer',
'min': 0,
},
'phones': {
'type': 'list',
'schema': {
'type': 'string',
'regex': '^[0-9]{2,4}-[0-9]{2,4}-[0-9]{3,4}$',
}
},
'address': {
'type': 'string',
'empty': True,
},
'birthday': {
'type': 'date',
}
}
# バリデータを作成
v = Validator(schema)
# 入力値1(バリデーションOK)
data_ok = {
'name': '田中一郎',
'email': 'tanaka@test.co.jp',
'age': 30,
'phones': [
'012-3456-7890',
'0120-444-444',
],
'address': '',
'birthday': date(1990, 7, 7),
}
# 入力値2(バリデーションNG)
data_ng = {
'name': '',
# 'email': 'tanaka@test.co.jp',
'age': -300,
'phones': [
'01234567890',
'skype',
],
'address': None,
'birthday': '1990-07-07',
'sex': 'male',
}
# バリデーション実施、結果表示
print("-----------------------------------------")
print("◯OK")
print("-----------------------------------------")
pprint(v.validate(data_ok))
pprint(v.errors)
print("-----------------------------------------")
print("×NG")
print("-----------------------------------------")
pprint(v.validate(data_ng))
pprint(v.errors)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment