Flask RESTful
why learn it?
Flask_RESTful —>快速构建REST API的Flask扩展
安装
pip install flask_restful
案列:
from flask import Flask
from flask_restful import Resouce, Api
app = Flask(__name__)
api = Api(app)
class DemoResource(Resource):
def get(self):
return {'hello': 'world'}
def post(self):
return {'msg': 'post hello world'}
api.add_resource(DemoResource, '/')
对比原生flask:
- 增加一个RESTful提供的Api类对象,用于收集类视图的注册信息。
- 收集:创建类视图——>类中的不同方法对应不同的请求资源。类继承自:Resource,返回**字典:**类型数据。
- 为类视图绑定路由:Add_resource(类视图。‘/路由信息’)
视图
1. 路由
- 添加:add_resource()
- 起名:endpoint=
app.add_resource(DemoResource, '/demo', endpoint = ”demo“)
2. 蓝图中使用
from flask import Flask,Blueprint
from flask_restful import Api, Resource
app = Flask(__name__)
user_bp = Blueprint('user',__name__)
user_api = Api(user_bp)
class UserProfileResource(Resource):
def get(self):
return {'msg':'get user profile'}
user_api.add_resource(UserProfileResource,'/user/profile', endpoint='userprofile')
app.register_blueprint(user_bp)
对比app中 使用restful和蓝图
- 使用蓝图
- 创建蓝图对象 : bp = Blueprint(‘name’,name)
- 用蓝图对象装饰器去装饰方法路由 :@bp.route(’’)
- 在主程序中注册蓝图:register_blueprint(bp)
- 蓝图中使用restful
- api = Api(bp) -->创建api对象时接收的参数不再时app(主程序),而是bp(蓝图)
- 采用restful 类视图函数而不是方法,不再使用装饰器
- api = Api(bp)------>收集数据------>bp
- api = Api(app)------收集数据------->全局flask
3. 装饰器
添加装饰器:method_decorators
- 为所有类视图添加相同装饰器
- 定义装饰器(1个或多个)
- 在类视图中添加装饰器
class DemoResource(Resource)
method_decorators = [decorator1, decorator2]
def ...
- 为不同类视图添加不同装饰器
method_decorators = {
'get': [decorator1, decorator2],
'post': [decorator1]
}
请求
flask_restful ----> RequestParser–>(检验、转换请求数据。)
步骤:
- 导包:from flask_restful import reqparse
- 创建requestparser对象:parser = reqparse.RequestParser()
- 向requestparser对象添加需要检验或转换的参数声明。add.argument()
- 启动检验:parse_args()
- 从结果中获取参数:—>字典/对象属性。
args.rate or args[‘rate’]
from flask_restful import reqparse
parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate cannot be converted', location='args')
parser.add_argument('name')
args = parser.parse_args()
参数说明
第三步,向requestparser对象中添加需要转化、检验的请求数据。
- required
描述一个请求时是否一定需要携带参数---->False
True:强制携带,未携带是返回状态码400
False:不要求强制,未携带取出None - help
请求参数校验错误返回错误信息的描述
rp.add_argument('a',required=True, help='missing a param')
- action
描述请求对象中出现多个同名参数的处理方式
- action = ‘store’ -------->保留第一个(默认)
- action= ‘append’
------->以列表追加保存所有同名参数的值—>like= [‘画画’, ‘唱歌’,‘摄影’]
- type
描述参数应该匹配的类型。
- python标准数据类型
rp.add_argument('a', type = int, required=True, help='miss a param', action='append')
- Flask-RESTful---->检验参数类型方法----->flask_resetful.inputs
- url
- regex(自定义正则表达式)
- natural 自然数0、1、2、3…
- positive 正整数 1、2、3
- int_range(low, high) 整数范围
(2)
from flask_restful import inputs
rp.add_argument('a',type = inputs.regex(r'^\d{2}&'))
(5)
rp.add_argument('a', type = inputs.int_range(1, 10))
- boolean
- 自定义
def mobile(mobile_str):
"""
检验手机号格式
:param mobile_str: str 被检验字符串
:return: mobile_str
"""
if re.match(r'^1[3-9]\d{9}$', mobile_str):
return mobile_str
else:
raise ValueError('{} is not a valid mobile'.format(mobile_str))
rp.add_argument('a', type=mobile)
- location
描述参数在请求数据中应该出现的位置。
location:
- form ------>请求数据的----->表单
- args----------------------------->querystring
- headers------------------------>request headers
- cookies-------------------------> http cookies
- json------------------------------>json
- files------------------------------>uploads
ofcurse! ------可指明多个位置
parser.add_argument('text',location=['headers','json'])
响应
序列化返回
Flask-RESTful提供了marshal---->将数据序列化为特定格式的字典数据---->作为视图的返回值。
任何对象--------->字典
- 装饰器用法:@marshal_with(resource_fields,envelope=‘resource’)
- 导包:from flask_ restful import Resource, fields, marshal_with,marshal
- 指定序列化字段:xx = {‘name’ : fields.type}
- marshal装饰器(marshal_with)为restful类视图中的get方法添加装饰器。
- 视图函数,获取某一对象,将得到的对象经过序列化返回。
from flask_restful import fields,marshal,marshal_with,Resource
resource_fields = {
'name':fields.String,
'age':fields.Integer
}
class DemoResource0(Resource):
@marshal_with(resource_fields,envelope='data')
def get(self):
user = User.object.get(id=1)
return user
class DemoResource1(Resource):
def get(self):
user = User.object.get(id=1)
# 除了指明字段和envelope之外,还需指明要处理的对象是谁。
return marshal(user, resource_fields,envelope='data')
envelope: 信封--------->{‘data’:{‘user’:‘小王’,‘age’:18}}
- marshal()返回
定制返回的json格式——representation装饰器
需求:规定接口返回的json数据具有统一的格式
{"message": "描述信息", "data": {要返回的具体数据}}
representation<-----------------Flask-RESTful的Api对象------------>定制返回数据的呈现格式。
representation:相当于哟个钩子,允许你挂个函数——指定返回数据格式
@api.representation('application/json')
def func()
处理内容
...
在视图函数中得到得返回数据,并不立刻直接返回给客户端,而是先经过被representation装饰得函数之后再返回。
method:
修改flask_restful.representations.json代码:
from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps
def output_json(data, code, headers=None):
"""Makes a Flask response with a JSON encoded body"""
# 此处为自己添加***************
if 'message' not in data:
data = {
'message': 'OK',
'data': data
}
# **************************
settings = current_app.config.get('RESTFUL_JSON', {})
# If we're in debug mode, and the indent is not set, we set it to a
# reasonable value here. Note that this won't override any existing value
# that was set. We also set the "sort_keys" value.
if current_app.debug:
settings.setdefault('indent', 4)
settings.setdefault('sort_keys', not PY3)
# always end the json dumps with a new line
# see https://github.com/mitsuhiko/flask/pull/1262
dumped = dumps(data, **settings) + "\n"
resp = make_response(dumped, code)
resp.headers.extend(headers or {})
return resp