python - flask-restx 如何从模型创建解析器
问题描述
我flask-restx
用于记录和格式化我的 api
我有一个应用程序,包括一个目录,以以下格式保存 json 模式:http: //json-schema.org/draft-07/schema#
(在我的应用程序中,它们保存为 json 文件,在下面的示例中我放它作为一个硬编码的字典来简化示例)
使用架构,我想实现 3 个目标:
- 文件
- 应要求验证
- 解析请求
使用@api.expect(request_model, validate=True)
我设法实现(1)和(2),但我没有找到使用现有模式解析的方法,我不得不创建一个解析器对象reqparse.RequestParser()
,并重写参数。
有没有办法RequestParser
从模型创建?(模型是从现有的 json 模式文件创建的)
这是我的代码:
from flask_restx import Api, inputs
api = Api(app, doc='/my_doc_path')
request_schema = {
'type': 'object',
'properties': {
'param1': {'type': 'string'},
'the_date': {"type": "string", "format": "date-time"},
},
'required': ['param1'],
}
request_model = api.schema_model('my_api_model', request_schema)
@api.route('/my_api/<string:id>')
class MyApi(Resource):
@api.expect(request_model, validate=True)
def post(self, id):
"""
my cool app
"""
parser = reqparse.RequestParser()
parser.add_argument('param1', help='some param 1')
parser.add_argument('the_date', type=inputs.datetime_from_iso8601, help='some date_time')
args = parser.parse_args()
do_something(args['param1'], args['the_date'])
有没有办法做到:
parser = reqparse.RequestParser(request_model)
args = parser.parse_args()
?
解决方案
我最终编写了代码以从架构中生成解析器:
def build_parser(schema):
parser = RequestParser()
for prop, conf in schema['properties'].items():
if conf.get('type') == 'string' and conf.get('format') == 'date-time':
parser.add_argument(prop, type=inputs.datetime_from_iso8601)
elif conf['type'] == 'integer':
parser.add_argument(prop, type=int)
elif conf['type'] == 'boolean':
parser.add_argument(prop, type=bool, default=False)
elif conf['type'] == 'array':
parser.add_argument(prop, default=list, action='append')
else:
parser.add_argument(prop)
return parser
我创建了以下装饰器类:
import functools
import inspect
class Rest:
@staticmethod
def route(api, route_str='', decorators=None):
decorators = decorators or []
def wrapper(cls):
for name, method in inspect.getmembers(cls, inspect.isfunction):
schema_name = getattr(method, '_schema_name', None)
if schema_name:
schema = getattr(method, '_schema', None)
setattr(cls, name, api.expect(api.schema_model(schema_name, schema), validate=True)(method))
cls.method_decorators = cls.method_decorators + decorators
return api.route(route_str)(cls) if route_str else cls
return wrapper
@staticmethod
def schema(schema_name, parse=False):
def decorator(f):
f._schema_name = schema_name
f._schema = get_api_schema(schema_name) # this function reads the json file
parser = build_parser(f._schema)
@functools.wraps(f)
def wrapper(*args, **kwargs):
if parse:
req_args = parser.parse_args()
return f(*args, req_args, **kwargs)
return f(*args, **kwargs)
return wrapper
return decorator
这是我使用它的方式:
@Rest.route(api, '/my_api/<string:id>')
class MyApi(Resource):
@Rest.route('my_api_schema_name', validate=True)
def post(self, args, id):
do_something(args['param1'], args['the_date'])
注意我写的装饰器会解析参数并将它们传递给post
函数
推荐阅读
- java - 将 Spring Boot 后端超时设置为无限期
- python - Pillow - 改变每个像素的 RGB 值
- reactjs - 我有一个关于在单击时将 id 传递到我的详细信息路线的问题
- kubernetes - Tiller 每 30 秒超时,无法继续安装
- angular7 - 订阅许多承诺?
- javascript - 具有反应形式值的节点 js 过滤器数组
- c# - .NET 4.0 图形库 - 如何捕获“整个”屏幕?
- libra - 将助记词恢复种子写入文件时出错:LibraWalletGeneric: Permission denied (os error 13)
- python - 我的年份列表不适用于 BeautifulSoup。为什么?
- python - 用户输入一个字母后,我需要打印上一个字母、输入的字母和下一个字母