flask自定义参数校验、序列化和反序列化
项目总体结构
我的工厂函数factory.py
from settings import setting
from flask import Flask
from models.models import db
from flask_migrate import Migrate
from urls.router import bp_te, bp_lo
# from flask_script import Manager
from utils.log import set_log
# from flask_limiter import Limiter
# from flask_limiter.util import get_remote_address
# https://www.cnblogs.com/Du704/p/13281032.html mysql_host = setting.MYSQL_HOST
mysql_port = setting.MYSQL_PORT
mysql_user = setting.MYSQL_USER
mysql_pwd = setting.MYSQL_PASSWORD
mysql_database = setting.MYSQL_DATABASE
env_cnf = setting.ENV_CNF def create_app():
set_log()
application = Flask(__name__)
DB_URI = f'mysql+pymysql://{mysql_user}:{mysql_pwd}@{mysql_host}:{mysql_port}/{mysql_database}'
application.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
# 是否追踪数据库修改,一般不开启, 会影响性能
application.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# 是否显示底层执行的SQL语句
application.config['SQLALCHEMY_ECHO'] = False # 初始化db,关联项目
db.app = application
db.init_app(application)
migrate = Migrate()
migrate.init_app(application, db) # 注册蓝图
application.register_blueprint(bp_te)
application.register_blueprint(bp_lo) # manager = Manager(application) return application application = create_app()
配置文件setting.py,读取数据库等配置信息
from configparser import ConfigParser
from pathlib import Path from utils.encryption import getDataAes BASE_DIR = Path(__file__).resolve().parent.parent conf = ConfigParser()
conf.read("config.ini", encoding='utf-8')
try:
mysqlhost = conf.get("mysql", "host")
mysqlport = conf.get("mysql", "port")
mysqluser = conf.get("mysql", "user")
mysqlpassword = conf.get("mysql", "password")
mysqlname = conf.get("mysql", "name") secret = conf.get('serve', 'secret')
env_cnf = conf.get('serve', 'env') redishost = conf.get("redis", "host")
redisport = conf.get("redis", "port")
redispwd = conf.get("redis", "password")
redislibrary = conf.get("redis", "library") MINIOHOST = conf.get("minio", "clienthost")
MINIOPORT = conf.get("minio", "clientport")
miniopwd = conf.get("minio", "password")
miniouser = conf.get("minio", "user")
MINIOWEBHOST = conf.get("minio", "webhost")
MINIOWEBPORT = conf.get("minio", "webport")
MINIOHTTP = conf.get("minio", "http") except Exception as e:
print(e)
mysqlhost = '127.0.0.1'
mysqlport = 3306
mysqluser = 'root'
mysqlpassword = '000000'
mysqlname = '0'
secret = 'Wchime'
env_cnf = 'develop' redishost = '127.0.0.1'
redisport = '6379'
redispwd = '000000'
redislibrary = "1" MINIOHOST = '127.0.0.1'
MINIOPORT = '9000'
MINIOWEBPORT = '9000'
miniopwd = '000000'
miniouser = '000000'
MINIOHTTP = 'http://'
MINIOWEBHOST = '127.0.0.1' MYSQL_HOST = mysqlhost
MYSQL_PORT = mysqlport
MYSQL_USER = getDataAes(secret, mysqluser)
MYSQL_PASSWORD = getDataAes(secret, mysqlpassword)
MYSQL_DATABASE = mysqlname REDIS_HOST = redishost
REDIS_PORT = redisport
REDIS_PASSWORD = getDataAes(secret, redispwd)
REDIS_LIBRARY = redislibrary MINIOPWD = getDataAes(secret, miniopwd)
MINIOUSER = getDataAes(secret, miniouser) ENV_CNF = env_cnf if __name__ == '__main__':
print(mysqlpassword)
models.py数据库模型文件
import datetime from utils.core import db
from sqlalchemy_serializer import SerializerMixin class Uu(db.Model, SerializerMixin): __tablename__ = 'uu'
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
name = db.Column(db.String(20), nullable=False)
age = db.Column(db.Integer, nullable=False) ux_id = db.Column(db.Integer, db.ForeignKey('ux.id', ondelete='SET NULL'), nullable=True)
ux = db.relationship('Ux', backref='uu') # , lazy='dynamic' des = db.Column(db.String(20), nullable=True) img = db.Column(db.String(128), nullable=True) class Ux(db.Model, SerializerMixin):
serialize_rules = ("-uu",)
__tablename__ = 'ux'
id = db.Column(db.Integer, autoincrement=True, primary_key=True)
name = db.Column(db.String(20), nullable=False)
序列化文件serializes.py
from models import models
from utils.base import Serialize, DeSerialize class TestSerialize(Serialize):
model = models.Uu
fields = ['id', 'name']
build_fiels = [
{'name': 'ux_name', 'source': 'ux.name'},
{'name': 'img', 'method': True}
] def get_img(self, instance):
return [] class TestDeSerialize(DeSerialize):
model = models.Ux
required_fields = ['name']
ser_fields = ['id', 'name']
base.py自定义序列化和反序列化和参数解析文件
from models.models import db
from flask_restful import abort
from sqlalchemy import inspect class DeSerialize(object):
"""
反序列化,增删改
"""
model = None
req_fields = None
other_fields = []
req_data = {}
insatance = None
ser_fields = [] def __init__(self, insatance=None, data={}):
self.insatance = insatance
self.req_data = data @property
def required_fields(self):
return self._get_fileds(self.req_fields) @property
def serializer_fields(self):
return self.ser_fields if self.ser_fields else self.model().serializable_keys def _get_fileds(self, fileds):
if fileds is None: values_valid = self.model().serializable_keys
else:
values_valid = fileds
values_valid = list(values_valid)
# 删除主键
try:
primary_key = list(map(lambda x: x.name, inspect(self.model).primary_key))[0]
if primary_key in values_valid:
values_valid.remove(primary_key)
except:
if 'id' in values_valid:
values_valid.remove('id')
return values_valid def _get_vaild_values(self):
vaild_dict = {}
err = 'request data is empty'
for key in self.required_fields:
value = self.req_data.get(key)
if value is None:
err = f'{key} is not required'
return False, err
vaild_dict[key] = value for key in self.other_fields:
value = self.req_data.get(key)
if value is None:
continue
vaild_dict[key] = value return vaild_dict, err def _create(self):
vaild_data, err = self._get_vaild_values()
if vaild_data:
try:
instance = self.model(**vaild_data)
db.session.add(instance)
db.session.commit()
self.insatance = instance
return True, 'success'
except:
err = 'please correct fileds'
return False, err
else:
return False, err def _update(self):
vaild_data, err = self._get_vaild_values()
if vaild_data:
try:
instance = self.insatance
if instance is None:
return False, 'not find data' for key, value in vaild_data.items():
setattr(instance, key, value) db.session.commit()
return True, 'success'
except:
err = 'please correct fileds'
return False, err
else:
return False, err def save(self):
if self.insatance is None:
ret, msg = self._create()
if ret is False:
abort(400, msg=msg) else:
ret, msg = self._update()
if ret is False:
abort(400, msg=msg) @property
def data(self):
if self.insatance is None:
msg = 'data is not save'
abort(500, msg=msg)
return self.insatance.to_dict(only=tuple(self.serializer_fields)) def delete(self):
if self.insatance is None:
msg = 'not find data'
abort(400, msg=msg)
else:
try:
db.session.delete(self.insatance)
db.session.commit()
except Exception:
msg = 'delete exception'
abort(400, msg=msg) class Serialize(object):
"""
序列化
"""
model = None
fields = "__all__"
modelsDatas = []
many = True
date_format = "%Y-%m-%d"
datetime_format = "%Y-%m-%d %H:%M:%S"
time_format = "%H:%M:%S" build_fiels = [] def __init__(self, serializers, many=True):
self.modelsDatas = serializers
self.many = many @property
def data(self):
li = []
try:
if self.many:
for data in self.modelsDatas:
da = data.to_dict(only=tuple(self.serializer_fields), date_format=self.date_format,
datetime_format=self.datetime_format, time_format=self.time_format)
da.update(self._get_build_files_values(data))
li.append(da)
else:
da = self.modelsDatas.to_dict(only=tuple(self.serializer_fields), date_format=self.date_format,
datetime_format=self.datetime_format, time_format=self.time_format)
da.update(self._get_build_files_values(self.modelsDatas))
li.append(da)
except Exception as e:
print(e)
msg = 'serialize error'
li.append(msg)
abort(500, msg=msg)
return li @property
def serializer_fields(self):
return self.fields if self.fields != "__all__" else self.model().serializable_keys def _get_build_files_values(self, data):
dit = {}
for build in self.build_fiels:
obj = data
if build.get('method'):
func = f"get_{build['name']}"
f = getattr(self, func)
value = f(obj)
dit[build['name']] = value
else:
source_list = build['source'].split('.')
value = None
for source in source_list: value = getattr(obj, source, None)
if value:
obj = value
else:
break
dit[build['name']] = value return dit class ParseQuery(object):
"""
查询,排序
"""
filer_query = frozenset(['gt', 'ge', 'lt', 'le', 'ne', 'eq', 'ic', 'ni', 'in']) def __init__(self, model, req_data, filter_list=[], order_by=None):
self.model = model
self.req_data = req_data
self.filter_list = filter_list
self.order_by = order_by self._operator_funcs = {
'gt': self.__gt_model,
'ge': self.__ge_model,
'lt': self.__lt_model,
'le': self.__le_model,
'ne': self.__ne_model,
'eq': self.__eq_model,
'ic': self.__ic_model,
'ni': self.__ni_model,
# 'by': self.__by_model,
'in': self.__in_model,
} @property
def _filter_data(self):
search_dict = {}
for fit in self.filter_list:
val = self.req_data.get(fit)
key = fit.split('__')[0]
if val and hasattr(self.model, key):
search_dict[fit] = val
return search_dict def _parse_fields(self):
li = []
for search_key, value in self._filter_data.items():
key, ope = search_key.split('__')
if ope in self.filer_query:
data = self._operator_funcs[ope](key=key, value=value)
li.append(data)
return li def _filter(self):
data = tuple(self._parse_fields())
quety_data = self.model.query.filter(*data)
if self.order_by:
data = self._parse_order_by()
quety_data = quety_data.order_by(*data)
return quety_data @property
def query(self):
return self._filter() def pagination_class(self, page_num=1, page_size=10, max_page_size=50, error_out=False):
pagin = self.query.paginate(
page=page_num,
per_page=page_size,
error_out=error_out,
max_per_page=max_page_size
)
return pagin.items, pagin.total def _parse_order_by(self):
"""
解析排序
:return:
"""
li = []
for ord in list(self.order_by):
if ord.find('-') == -1:
data = self.__by_model(ord)
if data:
li.append(data.asc())
else:
ord = ord[1:]
data = self.__by_model(ord)
if data:
li.append(data.desc())
return tuple(li) def __by_model(self, key):
"""
排序时获取字段
:return:
"""
return getattr(self.model, key) def __gt_model(self, key, value):
"""
大于
:param key:
:param value:
:return:
"""
return getattr(self.model, key) > value def __ge_model(self, key, value):
"""
大于等于
:param key:
:param value:
:return:
"""
return getattr(self.model, key) >= value def __lt_model(self, key, value):
"""
小于
:param key:
:param value:
:return:
"""
return getattr(self.model, key) < value def __le_model(self, key, value):
"""
小于等于
:param key:
:param value:
:return:
"""
return getattr(self.model, key) <= value def __eq_model(self, key, value):
"""
等于
:param key:
:param value:
:return:
"""
return getattr(self.model, key) == value def __ne_model(self, key, value):
"""
不等于
:param key:
:param value:
:return:
"""
return getattr(self.model, key) != value def __ic_model(self, key, value):
"""
包含
:param key:
:param value:
:return:
"""
return getattr(self.model, key).like('%{}%'.format(value)) def __ni_model(self, key, value):
"""
不包含
:param key:
:param value:
:return:
"""
return getattr(self.model, key).notlike('%{}%'.format(value)) def __in_model(self, key, value):
"""
查询多个相同字段的值
:param key:
:param value:
:return:
"""
return getattr(self.model, key).in_(value)
自定义序列化和反序列化后,接口将变得简单
上面的类视图将只有短短的几行代码
flask自定义参数校验、序列化和反序列化的更多相关文章
- 更加灵活的参数校验,Spring-boot自定义参数校验注解
上文我们讨论了如何使用@Min.@Max等注解进行参数校验,主要是针对基本数据类型和级联对象进行参数校验的演示,但是在实际中我们往往需要更为复杂的校验规则,比如注册用户的密码和确认密码进行校验,这个时 ...
- C# .net framework .net core 3.1 请求参数校验, DataAnnotations, 自定义参数校验
前言 在实际应用场景中我们常常要对接口的入参进行校验, 例如分页大小是否正确, 必填参数是否已经填写等等. 最简单的实现方式如下图, 这种在实际开发中代码过于冗余, 而且不灵活. 今天介绍一种统一参数 ...
- Go 命令行参数,JSON 序列化与反序列化
#### Go 命令行参数,JSON 序列,反序列化这一节来学习一下Go 如果解析命令行参数,以及JSON 的序列化及反序列化; 命令行参数对于熟悉Linux 的同学来说比较清楚,如: ls -a , ...
- go语言之行--文件操作、命令行参数、序列化与反序列化详解
一.简介 文件操作对于我们来说也是非常常用的,在python中使用open函数来对文件进行操作,而在go语言中我们使用os.File对文件进行操作. 二.终端读写 操作终端句柄常量 os.Stdin: ...
- 对类参数的序列化和反序列化XML
/// <summary> /// Xml序列化与反序列化 /// </summary> public class XmlUtil { #region 反序列化 /// < ...
- drf-序列化字段及参数、序列化和反序列化高级用法、ModelSerializer使用
1.序列化类常用字段和字段参数 1.1 常用字段类 1.BooleanField 2 NullBooleanField 3 CharField CharField(max_length=None, m ...
- springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)
一.引入相应的maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifa ...
- Flask开发技巧之参数校验
Flask开发技巧之参数校验 目录 Flask开发技巧之参数校验 1.请求参数分类 2.解决方案使用到的库 3.针对url查询参数与一般json格式 4.针对复杂json格式数据 本人平时开发中使用的 ...
- 【参数校验】 自定义校验器 (实现ConstraintValidator)
日常工作中写接口时,往往需要校验前端传来的枚举状态码,例如"1","2"等等, 这里使用java 303规范的参数校验框架封装一个自定义参数校验器: /** * ...
- DRF框架(二)——解析模块(parsers)、异常模块(exception_handler)、响应模块(Response)、三大序列化组件介绍、Serializer组件(序列化与反序列化使用)
解析模块 为什么要配置解析模块 1)drf给我们提供了多种解析数据包方式的解析类 form-data/urlencoded/json 2)我们可以通过配置来控制前台提交的哪些格式的数据后台在解析,哪些 ...
随机推荐
- 两款轻便且功能强大的gif截取工具 [ScreenToGif] 和 [GifCam]
轻便且强大 提示 下述工具下载链接为官方或github地址,可能会由于你懂得的原因,而无法打开. 一.ScreenToGif 软件简介: ScreenToGif 也是一款非常轻便的.完全免费的.没广告 ...
- vue 组件之间的自定义方法互相调用
1,先定义一个中间通信文件js globalBus.js import Vue from 'vue'; export const globalBus = new Vue(); 2,A.vue组件的方法 ...
- 【ASP.NET Core】MVC过滤器:运行流程
MVC 的过滤器(Filters)也翻译为"筛选器".但是老周更喜欢翻译为"过滤器",意思上更好理解. 既然都叫过滤器了,就是在MVC的操作方法调用前后进行特殊 ...
- Cadence SPB 22.1 -- 原理图的电器元件放置03Day
1.新增原理图:"SCHEMATIC"-->"New Page" 2.元器件放置 ①.添加原理图库 ②.放置元器件 选择对应元件库,再选择需要放置的元件, ...
- PX4安装环境测试
1.ROS环境测试 安装ROS版本:melodic roscore // 注意下面是打开一个新的终端,roscore一直在运行 rosrun turtlesim turtlesim_node // 再 ...
- 有序对的LCP
求\(\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n} LCP(s_i, s_j)\) 方法一 \(1.\)Trie . \(2.\)求\(cnt\),\(cnt[ ...
- N100低功耗win11安装wsl2当入门nas
前言 最近入了一台16gb+512gb的N100,想着用来存些资源,当个nas,偶尔要用用windows系统,所以想直接在这上面搞个虚拟机算了,WSL2似乎是一个不错的选择,下面介绍捣鼓的教程. 没用 ...
- 袋鼠云数栈前端从 Multirepo 到 Monorepo 研发效率提升探索之路
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:星野 困境频生前端代码管理何解? 前端代码管理一直是困扰着 ...
- MySQL 数据目录
MySQL 的数据目录 1. MySQL 的主要目录结构 方式1:通过命令搜索 find / -name mysql 方式2(推荐):通过查看配置文件获取目录结构 vim /etc/my.cnf (重 ...
- 基于WebRTC的局域网文件传输
基于WebRTC的局域网文件传输 WebRTC(Web Real-Time Communications)是一项实时通讯技术,允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点P2P ...