参考文档:https://flask-restful.readthedocs.io/en/latest/extending.html
自定义内容
假设我的 API 想添加一个字段 message
来放描述信息,如下:
{
"message": "user data",
"data": {"user": {"address": "20th street ", "name": "tom"}}
}
我们可以手工为每一个 Resource
类添加,但 Flask-RESTful
为我们提供了一个 representation
装饰器来实现对内容的自定义:
from flask import Flask, make_response
from flask_restful import (
Api,
Resource,
fields,
marshal_with
)
import json
app = Flask(__name__)
api = Api(app)
todos = {'1': {'name': 'tom', 'address': '20th street '}}
@api.representation('application/json')
def output_json(data, code, headers=None):
data = {
'message': 'user data',
'data': data
}
resp = make_response(json.dumps(data), code)
resp.headers.extend(headers or {})
return resp
resource_fields = {
'name': fields.String,
'address': fields.String,
}
class Todo(Resource):
@marshal_with(resource_fields, envelope='user')
def get(self, id):
# 这里实际操作中可写成用 ORM 模块获取对象实例的代码
return todos[id]
api.add_resource(Todo, '/<string:id>')
if __name__ == '__main__':
app.run(debug=True)
用 representation
装饰器的函数需要返回一个 Flask 的 Response
对象。
这个输出函数有三个参数,data
,code
和 headers
,data
就是传来的数据,code
是 HTTP 状态码,headers
是 HTTP 响应头。
自定义字段
继承 Raw
并且实现 format()
方法来自定义字段:
class AllCapsString(fields.Raw):
def format(self, value):
return value.upper()
resource_fields = {
'name': fields.String,
'all_caps_name': AllCapsString(attribute='name'),
}
自定义输入类型
对于解析参数,你可能想要自定义验证,这需要你创建你自己的输入类型。
# 自定义状态码转换
# 'init' => 0
# 'in-progress' => 1
# 'completed' => 2
def task_status(value):
statuses = [u"init", u"in-progress", u"completed"]
return statuses.index(value)
变量 value
是参数的值,变量 name
是参数名。
完整的例子:
def task_status(value):
statuses = [u"init", u"in-progress", u"completed"]
return statuses.index(value)
class Todo(Resource):
def __init__(self):
self.parser = reqparse.RequestParser(bundle_errors=True)
self.parser.add_argument('name', type=str, )
self.parser.add_argument('task_status', type=task_status)
def get(self):
args = self.parser.parse_args()
return args
api.add_resource(Todo, '/')
打开 API http://127.0.0.1:5000/?name=tom&task_status=init
可见:
{
"task_status": 0,
"name": "tom"
}
响应格式化
如果想使用其他响应格式(如:xml
、csv
、html
),可以使用representation()
装饰器。
api = Api(app)
@api.representation('text/csv')
def output_csv(data, code, headers=None):
pass
# implement csv output!
该装饰器修饰的函数需要输出一个 flask.Response
对象。
def output_json(data, code, headers=None):
"""Makes a Flask response with a JSON encoded body"""
resp = make_response(json.dumps(data), code)
resp.headers.extend(headers or {})
return resp
不使用装饰器还可以直接在 API
对象下设置:
app = Flask(__name__)
api = Api(app)
def output_json(data, code, headers=None):
data = {
'message': 'user data',
'data': data
}
resp = make_response(json.dumps(data), code)
resp.headers.extend(headers or {})
return resp
api.representations['application/json'] = output_json
资源方法装饰器
Resource
有一个叫做 method_decorators
的属性。你可以添加你自己的装饰器,该装饰器将会被添加到资源里面所有 method
函数。
# 自定义的装饰器
def deco(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('start')
return func(*args, **kwargs)
print('end')
return wrapper
class Todo(Resource):
# 现在 Todo 里面所有方法都会带上这个装饰器
method_decorators = [deco]
@marshal_with(resource_fields, envelope='user')
def get(self, id):
return todos[id]
网友评论