原则上,前端和后端我们都应该进行数据校验,单纯的把数据校验放前端做,后端不做任何数据校验是不合理的,那么,我们如何简洁地、快速地、或者说一劳永逸地完成这一步呢,现在,小编就手把手,带你一步一步完成后端的数据校验工作。
首先,在我们当前模块的models目录下新建一个类ValidateModel,如图:
用法,在需要数据校验的model模型类中,继承刚才新建立的ValidateModel类方法,如图:
然后,在model类中,定义好字段属性代码的下面,定义一个类的成员属性validation_rule字典,如图:
validation_rule字典中,key对应你想进行数据校验的字段名,value是当前需要校验字段的校验规则,也是一个字典,包含3个属性,分别是regex正则验证表达式,tip验证报错时的提示语,flags是正则表达式re.match函数的第三个参数,即“re.match(regex, value, flags)”。
具体应用,在需要调用模型的地方,用模型实例直接调用validate方法即可,如图:
最后贴上相关代码,validateModel.py代码:
import re
# 公共模块方法,通过配置正则的方式进行数据检验,模块基类
class ValidateModel:
'''
# 类成员属性,字典类型,数据检验规则配置
# 格式:
{
'field1': {
'regex': '\S+',
'tip': 'field1不能为空',
'flags': 0
},
'field2': {
'regex': '\S+',
'tip': 'field2不能为空',
'flags': 0
}
}
'''
validation_rule = {}
# 设置数据检验规则
def set_validation_rule(self, config=None):
if isinstance(config, dict) and config:
self.validation_config = config
# 获取数据检验规则
def get_validation_rule(self):
return self.validation_rule
# 数据校验
def validate(self, kw):
if not self.validation_rule:
return False, '请通过set_validation(config)方法设置数据检验规则'
err = [] # 错误存储
for key, item in self.validation_rule.items():
if key in kw:
value = kw.get(key)
if isinstance(item, list):
for it in item:
result, tip = self.valid(it, value)
if not result:
err.append(tip)
break
elif isinstance(item, dict):
result, tip = self.valid(item, value)
if not result:
err.append(tip)
if err:
break
if err:
return False, ', '.join(err)
return True, '验证通过'
# 单条检验
def valid(self, item, value):
if 'regex' in item and 'tip' in item:
regex = item['regex']
tip = item['tip']
flags = int(item['flags']) if 'flags' in item else 0
if not regex or not tip:
return False, '无效的检验配置,未设置正则(regex)或提示(tip)'
if not isinstance(flags, int):
flags = 0
result = re.match(regex, value, flags) # match(pattern, string, flags=0)
return True if result is not None else False, tip
return False, '无效的检验配置,未设置正则(regex)或提示(tip)'
模型继承类,根据你代码的实际位置引入ValidateModel类方法,代码:
from .models.validateModel import ValidateModel
# 设备公共表:公共字段,抽象类
class DeviceBase(models.AbstractModel, ValidateModel):
""" The base model, which is implicitly inherited by all device models. """
_name = "device.base"
_description = '设备基础模块'
# Many2many相互对应时,需要有name属性
name = fields.Char(string="名称")
# 设备基本信息
device_name = fields.Char(string="设备名称")
device_code = fields.Char(string="设备编号")
validation_rule = {
'device_name': {
'regex': '\S+',
'tip': '设备名称不能为空',
'flags': 0
},
'device_code': {
'regex': '\S+',
'tip': '设备编号不能为空',
'flags': 0
}
}
具体应用场景代码,数据入库时进行数据校验:
class DevicePushBase(Base):
models = "device.base" # 智能设备-基础模块
# 状态列表
status_list = [
'running_status',
'fault_alarm',
'hand_automatic_status',
]
# 更新数据时进行校验
@classmethod
def update_data(cls, kw):
model = request.env[cls.models].sudo()
validated, tip = model.validate(kw) # 进行数据校验
if not validated:
return 0, tip # 数据校验未通过,返回:0,报错提示
model.write(kw)
return 1, '编辑成功'
作者:周卫