feat: validate
This commit is contained in:
357
nc_http/tools/validate.py
Normal file
357
nc_http/tools/validate.py
Normal file
@@ -0,0 +1,357 @@
|
||||
import re
|
||||
import time
|
||||
|
||||
|
||||
class DataFormatValidator:
|
||||
"""
|
||||
参数验证类
|
||||
|
||||
示例:
|
||||
request_data = {'name': '51zan', 'type': 3,'desc':''}
|
||||
validate_rule = {
|
||||
'name': 'required|str|max:20', # 必须、字符串类型、最大20个字符
|
||||
'type': 'required|choices:0,1,2' # 必须、 取值范围【0,1,2】
|
||||
'desc': 'str' # 非必须,字符串
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, rules=None):
|
||||
"""
|
||||
:param rules: 验证规则
|
||||
"""
|
||||
rules = rules or []
|
||||
self.rules = rules
|
||||
self.error = ''
|
||||
self.valid_data = {}
|
||||
|
||||
def check(self, data):
|
||||
"""
|
||||
验证数据格式是否正确
|
||||
:param data: dict
|
||||
:return: boolean
|
||||
"""
|
||||
is_valid = True
|
||||
valid_data = {}
|
||||
for key, rule_str in self.rules.items():
|
||||
rules = rule_str.split("|")
|
||||
field_value = data.get(key)
|
||||
|
||||
# 如果字段不是必需的,没这个参数就不验证其它规则
|
||||
if 'required' not in rules and key not in data:
|
||||
continue
|
||||
|
||||
item_valid = True
|
||||
for rule in rules:
|
||||
if not rule:
|
||||
continue
|
||||
|
||||
combination_rule = rule.split(":", 1)
|
||||
if len(combination_rule) == 2:
|
||||
func = getattr(self, combination_rule[0].strip())
|
||||
args = combination_rule[1].split(',')
|
||||
if not func(field_value, *args):
|
||||
self.set_error(key, rule)
|
||||
item_valid = is_valid = False
|
||||
else:
|
||||
func = getattr(self, rule.strip())
|
||||
if not func(field_value):
|
||||
self.set_error(key, rule)
|
||||
item_valid = is_valid = False
|
||||
|
||||
# 如果当前项所有规则都验证通过,加入有效数据
|
||||
if item_valid:
|
||||
valid_data[key] = field_value
|
||||
|
||||
self.valid_data = valid_data
|
||||
return is_valid
|
||||
|
||||
def get_valid_data(self):
|
||||
return self.valid_data
|
||||
|
||||
def get_error(self):
|
||||
return self.error
|
||||
|
||||
def set_error(self, key, rule):
|
||||
self.error = self.error or "parameter {} is invalid, verified failed by method [{}]".format(key, rule)
|
||||
|
||||
@staticmethod
|
||||
def required(value):
|
||||
"""
|
||||
必需,不能为空
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if value in (None, ''):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def str(value):
|
||||
"""
|
||||
字符串
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if type(value) in (str,):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def int(value):
|
||||
if isinstance(value, int):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def number(value):
|
||||
"""
|
||||
数字
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
int(value)
|
||||
except ValueError:
|
||||
try:
|
||||
float(value)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def phrase(value):
|
||||
"""
|
||||
英文单词,短语
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if re.match(r'[a-zA-Z \']+$', value):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def float(value):
|
||||
"""
|
||||
浮点型
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if isinstance(value, float):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def bool(value):
|
||||
"""
|
||||
布尔型
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if isinstance(value, bool):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def dict(value):
|
||||
"""
|
||||
字典
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if type(value) == dict:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def ip(value):
|
||||
"""
|
||||
IP v4地址
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if re.match(r'^[\d]{1,3}(\.[\d]{1,3}){3}$', value):
|
||||
return True
|
||||
return False
|
||||
|
||||
def list(self, value, item_type=None):
|
||||
"""
|
||||
列表
|
||||
规则 list|list:str|list:int|list:ip|list:url
|
||||
:param value:
|
||||
:param item_type:
|
||||
:return:
|
||||
"""
|
||||
if type(value) not in (list, tuple):
|
||||
return False
|
||||
|
||||
if item_type:
|
||||
for item in value:
|
||||
func = getattr(self, item_type)
|
||||
if not func(item):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def max(value, max_value):
|
||||
"""
|
||||
验证字符串最大长度
|
||||
规则 max:2|max:10086
|
||||
:param value:
|
||||
:param max_value:
|
||||
:return:
|
||||
"""
|
||||
if len(value) > int(max_value):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def min(value, min_length):
|
||||
"""
|
||||
验证字符串最小长度
|
||||
规则 min:1|min:1024
|
||||
:param value:
|
||||
:param min_length:
|
||||
:return:
|
||||
"""
|
||||
if len(value) < int(min_length):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def length(value, valid_length):
|
||||
"""
|
||||
验证字符串长度
|
||||
规则 length:100
|
||||
:param value:
|
||||
:param valid_length:
|
||||
:return:
|
||||
"""
|
||||
if len(value) == int(valid_length):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def choices(value, *args):
|
||||
"""
|
||||
选项
|
||||
规则 choice:1,2,3|choice:a,b,c
|
||||
:param value:
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
if str(value) in args:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def excepts(value, *args):
|
||||
"""
|
||||
排除选项
|
||||
规则 choice:1,2,3|choice:a,b,c
|
||||
:param value:
|
||||
:param args:
|
||||
:return:
|
||||
"""
|
||||
if str(value) not in args:
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def range(value, min_length, max_length):
|
||||
"""
|
||||
数值区间
|
||||
规则 range:1,9|range:1,|range:,9
|
||||
:param value:
|
||||
:param min_length:
|
||||
:param max_length:
|
||||
:return:
|
||||
"""
|
||||
if min_length and value < int(min_length):
|
||||
return False
|
||||
if max_length and value > int(max_length):
|
||||
return False
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def url(value):
|
||||
"""
|
||||
URL
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if re.match(r'^https?:/{2}[\w\-_]+(\.[\w\-_]+)+.*$', value):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def email(value):
|
||||
"""
|
||||
邮箱
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if re.match(r'^[\w\-_]+@[\w\-_]+(\.[\w\-_]+)+$', value):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def mobile(value):
|
||||
"""
|
||||
手机号
|
||||
:param value:
|
||||
:return:
|
||||
"""
|
||||
if re.match(r'^1\d{10}$', value):
|
||||
return True
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def datetime(value, datetime_format):
|
||||
"""
|
||||
验证日期或时间格式
|
||||
规则 datetime:%Y-%m-%d %H:%M:%S | datetime:%Y-%m-%d
|
||||
:param value:
|
||||
:param datetime_format:
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
time.strptime(value, datetime_format)
|
||||
except ValueError:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_rules = {
|
||||
"id": "int|choices:2,3,4,5",
|
||||
"name": "required",
|
||||
"create_time": "int|range:,1000000",
|
||||
"remark": "required|str|max:5|min:1",
|
||||
"tags": "list:url",
|
||||
"avatar": "url",
|
||||
"email": "email",
|
||||
"mobile": "mobile",
|
||||
"birthday": "datetime:%Y-%m-%d %H:%M:%S",
|
||||
"ip": "ip",
|
||||
"department": "dict",
|
||||
"code": "number"
|
||||
}
|
||||
|
||||
test_data = {
|
||||
"id": 4,
|
||||
"name": "aaa",
|
||||
"create_time": 111111,
|
||||
"remark": "中国123",
|
||||
"tags": (u'http://baidu.com', 'http://baidu.com'),
|
||||
"avatar": "https://aaa111.com/a.php?a=b",
|
||||
"email": "ruyi111@sina.com",
|
||||
"mobile": "15880445400",
|
||||
"birthday": "2018-10-12 12:00:00",
|
||||
"ip": "111.1.1.1",
|
||||
"department": {"a": "b"},
|
||||
"code": '11.111'
|
||||
}
|
||||
|
||||
print(DataFormatValidator(test_rules).check(test_data))
|
Reference in New Issue
Block a user