开发

Flask-RESTPlus

2020-03-11  本文已影响0人  睡不醒的大橘

RESTful

RESTful 特点

  1. 资源:网络上的一个实体或具体信息。JSON是现在最常用的资源表示格式。
  2. 统一接口:数据的元操作,即CRUD操作,分别对应于HTTP方法:
  1. URI:URI是每一个资源的地址或识别符。最典型的URI即URL。
  2. 无状态:所有的资源,都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而改变。

RESTful 编写规范

Response数据和状态码(status code)

Flask-RESTPlus

(一)快速入门

pip install flask-restplus
路由(Routing)
from flask import Flask, request
from flask_restplus import Resource, Api

app = Flask(__name__)
api = Api(app)

todos = {}

@api.route('/<string:todo_id>')
class TodoSimple(Resource):
    def get(self, todo_id):
        return {todo_id: todos[todo_id]}

    def put(self, todo_id):
        todos[todo_id] = request.form['data']
        return {todo_id: todos[todo_id]}

if __name__ == '__main__':
    app.run()
  1. 通过传入Flask实例进行初始化
  2. Flask-RESTPlus提供的主要创建对象就是资源(Resource)。资源创建于Flask,可插入视图(pluggable view)之上,使得我们可以通过在资源上定义方法来很容易地访问多个HTTP方法。
  3. 在浏览器中直接访问我们API的根路径,即http://127.0.0.1:5000,此时会显示Swagger的界面,里面包含了我们的Restful API的相应信息。
  4. 可以从 python shell 中运行:
>>> from requests import put, get
>>> put('http://localhost:5000/todo1', data={'data': 'Remember the milk'}).json()
{'todo1': 'Remember the milk'}
>>> get('http://localhost:5000/todo1').json()
{'todo1': 'Remember the milk'}
>>> put('http://localhost:5000/todo2', data={'data': 'Change my brakepads'}).json()
{'todo2': 'Change my brakepads'}
>>> get('http://localhost:5000/todo2').json()
{'todo2': 'Change my brakepads'}
  1. Flask-RESTPlus理解视图方法中的多种类型的返回值。类似于Flask,你可以返回任何可迭代的类型,它会将该返回值转换成响应对象(response)。Flask-RESTPlus还提供了设置响应码和响应头的功能:
class Todo1(Resource):
    def get(self):
        # 默认为200 OK
        return {'task': 'Hello world'}

class Todo2(Resource):
    def get(self):
        # 设置响应码为201
        return {'task': 'Hello world'}, 201

class Todo3(Resource):
    def get(self):
        # 设置响应码为201,并返回自定义的响应头
        return {'task': 'Hello world'}, 201, {'Etag': 'some-opaque-string'}
端点 (Endpoints)
api.add_resource(TodoSimple, '/simple1', '/simple2')

# 或者下面装饰器方式,二者等价

@api.route('/simple1', '/simple2')
class TodoSimple(Resource):
    pass
命名空间 (Namespace)
from flask_restplus import Namespace
ns = Namespace('node', description='node operations', path='/root')
api.add_namespace(ns)

@ns.route('/simple')
class TodoSimple(Resource):
    def get(self, todo_id):
        return {'simple1': 'simple2'}

(二)请求解析(Argument Parsing)

from flask import Flask
from flask_restplus import Resource, Api, reqparse

app = Flask(__name__)
api = Api(app)

todos = {}

parser = reqparse.RequestParser()
parser.add_argument('data', type=int, required=True, help='data cannot be converted.')
parser.add_argument('name', type=str)

@api.route('/<string:todo_id>')
class TodoSimple(Resource):
    def put(self, todo_id):
        args = parser.parse_args()
        todos[todo_id] = args['data']
        return {todo_id: todos[todo_id]}

if __name__ == '__main__':
    app.run()
>>> put('http://localhost:5000/todo1', data={'data': '1'}).json()
{'todo1': 1}
>>> put('http://localhost:5000/todo1', data={}).json()
{'errors': {'data': 'Missing required parameter in the JSON body or the post body or the query string'}, 'message': 'Input payload validation failed'}
>>> put('http://localhost:5000/todo1', data={'data': 'a'}).json()
{'errors': {'data': "data cannot be converted. invalid literal for int() with base 10: 'a'"}, 'message': 'Input payload validation failed'}
参数位置
# 仅在 POST body中查找
parser.add_argument("method", location="form")

# 仅在querystring中查找
parser.add_argument("PageSize", location="args")

# 从请求头中查找
parser.add_argument("User-Agent", location="headers")

# 从http cookies中查找
parser.add_argument("session_id", location="cookies")

# 从上传文件中查找
parser.add_argument("picture", type=werkzeug.datastructures.FileStorage, location="files")

# 内部调用get_json(),可通过字典的方式获取键值,如果没有对应的键,那么会返回HTTP 400错误响应
parser.add_argument("name", location="json")
@api.expect()
from flask import Flask
from flask_restplus import Resource, Api, reqparse, fields

app = Flask(__name__)
api = Api(app)

todos = {}
model = api.model('model', {
    'data': fields.Integer,
})

@api.route('/<string:todo_id>')
class TodoSimple(Resource):
    @api.expect(model, validate='True')
    def put(self, todo_id):
        pass

if __name__ == '__main__':
    app.run()
自定义验证
def odd_number(value):
    if value % 2 == 0:
        raise ValueError("Value is not odd")
    return value

parser = reqparse.RequestParser()
parser.add_argument('data', type=odd_number, required=True, location='json')
上一篇 下一篇

猜你喜欢

热点阅读