一个最小的Flask应用
# encoding:utf-8
# app.py
from flask import Flask, jsonify, request
__author__ = '零四二零'
app = Flask(__name__)
@app.route('/', methods=['GET'])
def fight():
name = request.args.get('name')
return jsonify(dict(data=name))
# encoding:utf-8
# runserver.py
from app import app
__author__ = '零四二零'
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000, threaded=True)
请求http://0.0.0.0:5000?name=123
一个简单的想法是在函数内部判断name
的属性,不符合就返回错误信息,实现起来很简单
# encoding:utf-8
# app.py
from flask import Flask, jsonify, request
__author__ = '零四二零'
app = Flask(__name__)
@app.route('/', methods=['GET'])
def fight():
name = request.args.get('name', '')
if not name:
return jsonify(dict(error='缺少参数'))
try:
name = int(name)
except ValueError:
return jsonify(dict(error='参数格式错误'))
return jsonify(dict(data=name))
请求http://0.0.0.0:5000
请求http://0.0.0.0:5000?name=fight
这种写法非常不美,把类型判断剥离开来,改成装饰器,统一调用
# encoding:utf-8
# validator.py
from flask import request, jsonify
__author__ = '零四二零'
def validator_int(func):
def _decorate():
name = request.args.get('name', '')
if not name:
return jsonify(dict(error='缺少参数'))
try:
name = int(name)
except ValueError:
return jsonify(dict(error='参数格式错误'))
return func()
return _decorate
# encoding:utf-8
# app.py
from flask import Flask, jsonify, request
from validator import validator_int
__author__ = '零四二零'
app = Flask(__name__)
@app.route('/', methods=['GET'])
@validator_int
def fight():
name = request.args.get('name', '')
return jsonify(dict(data=name))
😎大功告成,继续优化,使用Flask
的异常处理,并支持默认参数
# encoding:utf-8
# validator.py
from flask import request
__author__ = '零四二零'
def validator_int(func):
def _decorate():
arg = request.args.get('name', '666')
if not arg:
raise Exception('缺少参数')
try:
name = int(arg)
except ValueError:
raise Exception('参数格式错误')
return func(arg)
return _decorate
# encoding:utf-8
# app.py
from flask import Flask, jsonify
from validator import validator_int
__author__ = '零四二零'
app = Flask(__name__)
@app.errorhandler(Exception)
def error(e):
return jsonify(dict(error=e.message))
@app.route('/', methods=['GET'])
@validator_int
def fight(name):
return jsonify(dict(data=name))
请求http://0.0.0.0:5000
默认是写在
validator_int
里并不是最好的选择,移到fight
中,需要用到inspect
库来获取fight
的参数信息
# encoding:utf-8
# app.py
from flask import Flask, jsonify
from validator import validator_int
__author__ = '零四二零'
app = Flask(__name__)
@app.errorhandler(Exception)
def error(e):
return jsonify(dict(error=e.message))
@app.route('/', methods=['GET'])
@validator_int
def fight(name='666'):
return jsonify(dict(data=name))
# encoding:utf-8
# validator.py
import inspect
from flask import request
__author__ = '零四二零'
def validator_int(func):
def _decorate():
arg = request.args.get('name', '')
if not arg:
func_args = inspect.getargspec(func)
defaults = func_args.defaults[0]
arg = func_args.args[0]
try:
name = int(defaults)
except ValueError:
raise Exception('参数格式错误')
return func(**{arg: defaults})
return _decorate
支持多参数操作,有默认值的加上默认值
# encoding:utf-8
# validator.py
import inspect
import json
from flask import request
__author__ = '零四二零'
REQUEST_METHOD_MAP = {'GET': 'args', 'POST': 'form'}
def _params_covert(val):
val = val[0] if isinstance(val, list) else val
try:
val = json.loads(val)
except (ValueError, TypeError):
pass
return val
def _get_request_params():
params = request.json or {}
for k, v in dict(getattr(request, REQUEST_METHOD_MAP.get(request.method))).iteritems():
params[k] = _params_covert(v)
return params
def _param_int_validator(val):
try:
_ = int(val)
except (ValueError, TypeError):
return False
return True
def validator_int(func):
def _decorate():
params = _get_request_params()
func_args = inspect.getargspec(func)
default_val, args, kwargs, args_len = func_args.defaults or [], [], {}, len(func_args.args)
for index, func_arg in enumerate(func_args.args):
default_index = index + len(default_val) - args_len
if default_index < 0:
if func_arg not in params:
raise Exception('缺少参数:{0}'.format(func_arg))
else:
if not _param_int_validator(params[func_arg]):
raise Exception('参数格式错误')
args.append(params[func_arg])
else:
kwargs[func_arg] = params[func_arg] if func_arg in params else default_val[default_index]
for k, v in kwargs.iteritems():
if not _param_int_validator(v):
raise Exception('参数:{0} 格式错误'.format(k))
return func(*args, **kwargs)
return _decorate
# encoding:utf-8
# app.py
from flask import Flask, jsonify
from validator import validator_int
__author__ = '零四二零'
app = Flask(__name__)
@app.errorhandler(Exception)
def error(e):
return jsonify(dict(error=e.message))
@app.route('/', methods=['GET'])
@validator_int
def fight(sex, name='666', age='18'):
return jsonify(dict(name=name, age=age, sex=sex))
请求http://0.0.0.0:5000?sex=1
再接再厉,支持指定参数类型判断,validator_int
需要接受一个dict
参数,里面是各个参数的字段类型
# encoding:utf-8
# validator.py
import inspect
import json
from flask import request
__author__ = '零四二零'
REQUEST_METHOD_MAP = {'GET': 'args', 'POST': 'form'}
def _params_covert(val):
val = val[0] if isinstance(val, list) else val
try:
val = json.loads(val)
except (ValueError, TypeError):
pass
return val
def int_field(value):
try:
_ = int(value)
except (ValueError, TypeError):
return False
return True
def str_field(value):
try:
import re
if not re.compile('.*').match(value):
return False
except (ValueError, TypeError):
return False
return True
def list_field(value):
try:
if not isinstance(value, list):
value = json.loads(value)
_ = [x.strip() for x in value.split(',')]
except (ValueError, TypeError):
return False
return True
def dict_field(value):
try:
if not isinstance(value, dict):
_ = json.loads(value)
except (ValueError, TypeError):
return False
return True
def bool_field(value):
try:
bool(value)
except (ValueError, TypeError):
return False
return True
def float_field(value):
try:
_ = float(value)
except (ValueError, TypeError):
return False
return True
def _get_request_params():
params = request.json or {}
for k, v in dict(getattr(request, REQUEST_METHOD_MAP.get(request.method))).iteritems():
params[k] = _params_covert(v)
return params
def validator_int(param_fields):
def _decorate(func):
def __decorate():
params = _get_request_params()
func_args = inspect.getargspec(func)
default_val, args, kwargs, args_len = func_args.defaults or [], [], {}, len(func_args.args)
for index, func_arg in enumerate(func_args.args):
if func_arg not in param_fields:
raise Exception('参数:{0}, 未指明类型'.format(func_arg))
default_index = index + len(default_val) - args_len
param_func = param_fields[func_arg]
if default_index < 0:
if func_arg not in params:
raise Exception('缺少参数:{0}'.format(func_arg))
else:
if not param_func(params[func_arg]):
raise Exception('参数:{0}格式错误, 需要类型:{1}'.format(func_arg, param_func.__name__))
args.append(params[func_arg])
else:
kwargs[func_arg] = params[func_arg] if func_arg in params else default_val[default_index]
for k, v in kwargs.iteritems():
if not param_fields[k](v):
raise Exception('参数:{0} 格式错误, 需要类型:{1}'.format(k, param_fields[k].__name__))
return func(*args, **kwargs)
return __decorate
return _decorate
# encoding:utf-8
# app.py
from flask import Flask, jsonify
from validator import validator_int, int_field, dict_field, list_field
__author__ = '零四二零'
app = Flask(__name__)
@app.errorhandler(Exception)
def error(e):
return jsonify(dict(error=e.message))
@app.route('/', methods=['GET'])
@validator_int(dict(name=dict_field, sex=list_field, age=int_field))
def fight(sex, name, age=18):
return jsonify(dict(name=name, age=age, sex=sex))
请求http://0.0.0.0:5000?sex=[1,2,3]&name={"name":"fight"}
请求
http://0.0.0.0:5000?sex=[1,2,3]&name=123
image.png
「欢迎分享,优化」
网友评论