优化了参数校验
MyRequestParseUtil
添加了参数isExist
、 参数都是模型类、通过name
获取带校验id
不存在raise
添加了参数unique
参数都是模型类、通过name
获得field
去查询是否重名
这俩参数 只针对
post
请求创建新的数据、对于put
修改时候没有去兼容、要不就是重复校验、要不就是会出现意想不到的错误
# 校验cls ID
if kw.get("isExist"):
cls = kw.get("isExist")
cls.get(self.body.get(kw['name']), kw['name'])
# 校验cls 重名
if kw.get("unique"):
cls = kw.get("unique")
cls.verify_unique(**{kw['name']: self.body.get(kw['name'])})
#--------------------------------------------------------------------------------
class Base(db.Model):
@classmethod
def get(cls, ident: int, name: AnyStr = None):
"""
get entity by id
:param ident: field id
:param name: field name
:return: get_or_NoFound
"""
return cls.query.get_or_NoFound(ident, name)
@classmethod
def verify_unique(cls, **kwargs) -> None:
"""verify_unique by field name"""
rv = cls.query.filter_by(**kwargs).first()
if rv:
raise ParamException(ResponseMsg.already_exist(list(kwargs.values())[0]))
#--------------------------------------------------------------------------------
class MyBaseQuery(BaseQuery):
def get_or_NoFound(self, ident, name) -> Any:
"""
get self by id
:param ident: id
:param name: cls.__name__
:return: cls.self
:raise:ParamException
"""
rv = self.get(ident)
if not rv:
raise ParamException(ResponseMsg.no_existent(name))
return rv
参数校验完整代码
也有优化了一些对于 是否必传等逻辑问题、
class MyRequestParseUtil:
def __init__(self, location: AnyStr = "json"):
"""
:param location: "json" -> application/json | "values" -> query default json
"""
self.location = location
self.args = []
try:
self.body = getattr(request, self.location, {})
except Exception as e:
log.error(e)
raise ParamException(ResponseMsg.REQUEST_BODY_ERROR)
def add(self, **kwargs):
"""
添加请求数据与数据类型
:param kwargs: name
:param kwargs: type
:param kwargs: required bool
:param kwargs: default
:param kwargs: choices
:param kwargs: isExist=cls put 请求主键还会再校验一次 不需要添加 添加外键
:param kwargs: unique put 不要添加
"""
# 默认类型为字符
if not kwargs.get("type"):
kwargs.setdefault("type", str)
# 默认非必传
if not kwargs.get("required"):
kwargs.setdefault("required", False)
self.args.append(kwargs)
def parse_args(self) -> Dict:
"""
参数校验
:return: self.body
"""
self.body = dict(self.body)
for kw in self.args:
# 分页数据
if kw["name"] == "page":
self.body[kw["name"]] = self.__verify_page(self.body.get(kw['name'], kw.get("default")))
if kw['name'] == "limit":
self.body[kw["name"]] = self.__verify_limit(self.body.get(kw["name"], kw.get("default")))
# 必传
if kw['required'] is True:
self.__verify_empty(self.body.get(kw["name"]), kw["name"])
# 非必传
else:
# 未传
if self.body.get(kw["name"]) is None:
if kw.get('default'):
self.body[kw['name']] = kw.get('default')
else:
continue
self.__verify_type(self.body.get(kw["name"]), kw['type'])
if kw.get("choices"):
self.__verify_choices(self.body.get(kw["name"]), kw['choices'])
# 校验cls ID
if kw.get("isExist"):
cls = kw.get("isExist")
cls.get(self.body.get(kw['name']), kw['name'])
# 校验cls 重名
if kw.get("unique"):
cls = kw.get("unique")
cls.verify_unique(**{kw['name']: self.body.get(kw['name'])})
return self.body
def __verify_page(self, page: AnyStr) -> int:
"""
page校验
:param page: 页
:raise: ParamException
:return page
"""
if int(page) < 1:
raise ParamException(ResponseMsg.error_param("page", "must > 0"))
return page
def __verify_limit(self, limit: AnyStr) -> int:
"""
limit 校验
:param limit: 行
:return: limit
"""
if int(limit) < 0:
raise ParamException(ResponseMsg.error_param("limit", "must > 0"))
return limit
def __verify_empty(self, target: AnyStr, filed: AnyStr):
"""
校验参数是否为空
:param target: 目标值
:param filed: 参数名
:raise: ParamException
"""
if target is None or target == "":
raise ParamException(ResponseMsg.empty(filed))
def __verify_type(self, target: Any, t: type, ):
"""
校验类型
:param target: 目标值
:param t: 期望类型
:raise: ParamException
"""
if not isinstance(target, t):
raise ParamException(ResponseMsg.error_type(target, t))
def __verify_choices(self, target: Any, choices: List):
"""
区间校验
:param target: 目标值
:param choices:
:raise: ParamException
"""
if target not in choices:
raise ParamException(ResponseMsg.error_val(target, choices))
使用
class CaseController(Resource):
@auth.login_required
def post(self) -> MyResponse:
parse = MyRequestParseUtil()
parse.add(name="title", type=str, required=True, unique=Cases)
parse.add(name="versionID", type=int, isExist=Version, required=True)
parse.add(name="steps", type=dict, required=True)
...
case = parse.parse_args()
Cases(**case).save()
return MyResponse.success()
关于修改
封装了个
update
通过cls.__table__.columns
修改其属性
但还是要通过get
获取实体对象
修改的时候把id
主键pop
出去
class Base(db.Model):
def save(self):
"""save"""
try:
db.session.add(self)
db.session.commit()
except Exception as e:
log.error(e)
db.session.rollback()
raise MyException()
@classmethod
def update(cls, **kwargs):
"""
通过kwargs.get('id') 获得实例 修改
"""
target = cls.get(kwargs.pop('id'))
c = [i.name for i in cls.__table__.columns]
for k, v in dict(kwargs).items():
if k in c:
setattr(target, k, v)
target.save()
使用update
项目实体修改 需要
ADMIN
orProjectADMIN
需要做个权限校验
通过flask
的g
获得user
使用super
调用父类update
整个更新过程中通过get
查询了两次库、暂时没想到怎么优化
class Project(Base):
@classmethod
def update(cls, **kwargs):
"""
添加权限过滤
必须是ADMIN or AdminID
:param kwargs: Project
"""
from flask import g
target = cls.get(kwargs.get('id'), f"{cls.__name__} id")
if not g.user.admin or not g.user.id != target.adminID:
raise AuthException()
return super(Project, Project).update(**kwargs)
class ProjectController(Resource):
@auth.login_required
def put(self) -> MyResponse:
"""
维护
:return: MyResponse
"""
from Models.UserModel.users import User
parse = MyRequestParseUtil()
parse.add(name="id", type=int, required=True)
parse.add(name="name", type=str, required=False)
parse.add(name="desc", type=str, required=False)
parse.add(name="adminID", type=int, isExist=User, required=False)
Project.update(**parse.parse_args())
return MyResponse.success()
写道最后
目前进度就是这样、有的模块没有录入 flask 也是边写边学、有好的想法的大佬可以留言。thank u
附上github github