美文网首页
Flask-RESTful 扩展

Flask-RESTful 扩展

作者: SingleDiego | 来源:发表于2020-06-09 15:27 被阅读0次

参考文档: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 对象。

这个输出函数有三个参数,datacodeheadersdata 就是传来的数据,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"
}




响应格式化

如果想使用其他响应格式(如:xmlcsvhtml),可以使用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]

相关文章

网友评论

      本文标题:Flask-RESTful 扩展

      本文链接:https://www.haomeiwen.com/subject/dfgstktx.html