美文网首页开发
Flask-RESTPlus

Flask-RESTPlus

作者: 睡不醒的大橘 | 来源:发表于2020-03-11 18:28 被阅读0次

RESTful

RESTful 特点

  • REST即Representational State Transfer的缩写。REST最大的几个特点为:资源、统一接口、URI和无状态。
  1. 资源:网络上的一个实体或具体信息。JSON是现在最常用的资源表示格式。
  2. 统一接口:数据的元操作,即CRUD操作,分别对应于HTTP方法:
  • GET用来获取资源
  • POST用来新建资源(也可用于更新资源)
  • PUT用来更新资源
  • DELETE用来删除资源。
  1. URI:URI是每一个资源的地址或识别符。最典型的URI即URL。
  2. 无状态:所有的资源,都可以通过URI定位,而且这个定位与其他资源无关,也不会因为其他资源的变化而改变。

RESTful 编写规范

Response数据和状态码(status code)

Flask-RESTPlus

(一)快速入门

  • Flask-RESTPlus是对Flask的扩展,它增加了对快速开发REST API的支持。Flask-RESTPlus中提供了大量的装饰器和工具来描述你的API,并以文档化的形式将这些接口展现出来(通过Swagger来实现)。

  • 安装

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()方法或route()装饰器中传入多个URL,这样每个URL都将会路由到该资源上
api.add_resource(TodoSimple, '/simple1', '/simple2')

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

@api.route('/simple1', '/simple2')
class TodoSimple(Resource):
    pass
  • 如果一个请求(request)与应用的任何端点都不匹配,那么Flask-RESTPlus将会返回一个404错误信息,并给出其他与所请求端点最匹配的建议信息。
命名空间 (Namespace)
  • 作用是为不同的资源,不同的url分组
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)

  • Flask-RESTPlus内置支持对请求数据的验证,这一功能是通过使用一个类似于argparse的库来实现的:
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()
  • parse_args()返回的是一个Python字典
  • 如果一个参数未验证通过,Flask-RESTPlus将响应一个400 Bad Request。如果你指定了 help 参数的值,在解析的时候当类型错误被触发的时候,它将会被作为错误信息给呈现出来。如果你没有指定 help 信息的话,默认行为是返回类型错误本身的信息。
  • 在默认情况下,参数不是必需的。而且,在请求中提供的参数不属于 RequestParser 的一部分的话将会被忽略。可以在调用parse_args时传入strict=True,以确保在请求中包含解析器没有定义的参数时抛出错误。
>>> 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'}
参数位置
  • 默认下,RequestParser 试着从 flask.Request.values,以及 flask.Request.json 解析值。
  • 在 add_argument() 中使用 location 参数可以指定解析参数的位置。flask.Request 中任何变量都能被使用。例如:
# 仅在 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()
  • @api.expect()装饰器允许你指定request body中期望的field,可以通过validate指定是否需要对其进行验证。
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()
自定义验证
  • 对于解析参数,可以执行自定义验证, 然后你可以在RequestParser 中使用这些自定义的输入类型:
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')

相关文章

  • Flask-RESTPlus

    RESTful RESTful 特点 REST即Representational State Transfer的缩...

网友评论

    本文标题:Flask-RESTPlus

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