1. 程式人生 > 程式設計 >使用 Flask-RESTPlus 構建 REST API

使用 Flask-RESTPlus 構建 REST API

平時寫專案時都是使用 Flask 原生的路由構建 API,最近接觸到 Flask-RESTPlus,它不僅能夠非常方便的構建 REST API,還可以生成 Swagger 檔案,我將通過兩篇文章分別介紹它們. 本文是對此擴充套件學習的總結,如有錯誤,歡迎指正~

安裝

pip install flask-restplus
複製程式碼

初始化

初始化 Flask 擴充套件 的方式有兩種,一種是直接傳入 Flask 例項:

from flask import Flask
from flask_restplus import Api

app = Flask(__name__)
api = Api(app)
複製程式碼

另一種,如果 Flask 例項 是通過 工廠函式 建立的,可以使用 init_app 方法:

from flask import Flask
from flask_restplus import Api

api = Api()
def create_app(config_name=None):
    """工廠函式"""
    app = Flask(__name__)
    api.init_app(app)
    return app
複製程式碼

當然,如果你使用了藍圖,可以使用藍圖初始化,然後將藍圖註冊到 Flask 例項 上:

from flask import Blueprint,Flask
from
flask_restplus import Api app = Flask(__name__) # 建立藍圖物件,並將Api物件掛載到上面 api_v1_bp = Blueprint('api_v1',__name__,url_prefix='/api/v1') api = Api(api_v1_bp,doc='') # 註冊藍圖 app.register_blueprint(api_v1_bp) 複製程式碼

最小示例

from flask import Flask
from flask_restplus import Api,Resource

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

@api.route('/hello')
class HelloWorld(Resource): def get(self): return {'hello': 'world'} 複製程式碼

建立 Api 物件後就可以使用它構建路由,構建路由首先建立一個資源類並繼承 Resource 類,Resource 類其實繼承了 Flask 本身提供的 MethodView 類,MethodView 類可以讓我們以 的方式組織 檢視函式,整個類作為一個 資源端點,使用 HTTP 方法 作為 類方法名,然後對應方法的請求就會被處理.

這裡以 GET 方法請求 /hello 將得到 {'hello': 'world'}. 如果訪問 / 根路由會發現進入如下所示的檔案頁面,這是因為 Api 物件將 檔案路由 預設掛載到 / 根路由,並且會自動渲染資源類,不過如果不需要開啟檔案功能,建立 Api 物件時可以將 doc 引數設定為 空字串,就像這樣 api = Api(app,doc='')

檔案

資源路由

上節提到,繼承 Resource 後的類稱為 資源類,給這個類新增路由,就可以完成基本的 CURD 功能,這裡使用一個 todos 作為示例:

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

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

todos = []

@api.route('/todos')
class TodoList(Resource):
    def get(self):
        """獲取所有TODO列表"""
        return todos

    def post(self):
        """新增一個TODO"""
        todos.append(request.json.get('todo'))
        return {'todo': request.json.get('todo')},201
        
@api.route('/todos/<int:index>')
class TODOItem(Resource):
    def get(self,index):
        """獲取"""
        return {'todo': todos[index]}

    def put(self,index):
        """修改"""
        todos[index] = request.json.get('todo')
        return {'todo': todos[index]}

    def delete(self,index):
        """刪除"""
        todo = todos.pop(index)
        return {'todo': todo},204
複製程式碼

如上所示,建立兩個資源類,分別表示對 所有資料單個資料 的操作. 單個資料路由引數 將自動傳遞給方法. 在方法體內編寫業務邏輯即可.

名稱空間

todos 例子中,所有路由都是用同一個 Api 物件,如果路由多了,就會變得難以管理,所以 flask-restplus 提供了類似於 藍圖名稱空間 功能. 一個名稱空間代表一個資源,使用了名稱空間後,就可以將資源隔離. 將 todos 例子改造一下:

from flask import Flask,Resource,Namespace

app = Flask(__name__)
api = Api(app,doc='')

# 建立 todos 名稱空間
ns = Namespace('todos',description='待辦列表')

api.add_namespace(ns)

todos = []

# 使用名稱空間進行路由管理
@ns.route('')
class TODOList(Resource):
    def get(self):
        """獲取所有TODO列表"""
        return todos

    def post(self):
        """新增一個TODO"""
        todos.append(request.json.get('todo'))
        return {'todo': request.json.get('todo')},201


@ns.route('/<int:index>')
class TODOItem(Resource):
    def get(self,204
複製程式碼

todos 名稱空間下,根路由為 /todos,這樣只需要關注當前資源下的路由即可.

裝飾器

如果想要給一些檢視函式新增裝飾器,比如 登陸驗證,常規的方法是給每個函式單獨新增,但是,flask-restplus 提供了更加方便的類屬性 method_decorators,它是一個列表,內部會遍歷這個列表裝飾每一個類方法. 示例如下所示:

@api.route('/todos/<int:index>')
class TODOItem(Resource):
    # 裝飾函式列表
    method_decorators = [auth_required]
複製程式碼

引數過濾

flask-restplus 同時提供了引數過濾功能,一個引數過濾器是一個 RequestParser 物件,然後呼叫例項方法 add_argument 新增引數,最後使用 parse_args 過濾引數即可:

from flask_restplus import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate',type=int,help='Rate cannot be converted')
parser.add_argument('name')
args = parser.parse_args()
複製程式碼

add_argument 方法的第一個引數表示 引數名,其餘關鍵字引數如下:

  • type: 引數資料型別
  • required: 是否為必傳引數
  • location: 引數位置,內部會通過 request.* 獲取
    • args
    • json
    • form
    • headers
    • cookies
    • etc
  • help: 引數描述

更詳細的引數過濾方式,請參考 檔案.

官方檔案提示,使用此方法過濾引數的功能將會在 2.0 版本被廢棄,屆時將會採用類似於 marshmallow 的序列化工具進行引數驗證,其實 flask-restplus 本身提供了 序列化 功能,但功能相對薄弱,同時也沒有 反序列化 功能,所以用起來不是很方便.

響應序列化

flask-restplus 提供了 marshal_with 裝飾器對響應進行序列化解析,但是我使用起來感覺不是很方便,所以我一般不使用此裝飾器,而是使用 marshmallow 庫進行序列化和反序列化. 具體 marshal_with 裝飾器的使用方式可以參考 檔案

總結

相對於 Flask 提供的 MethodView,flask-restplus 的使用方式是一致的,同時其增加的 名稱空間 更加方便了分離每一個資源. 不過它還提供了更加方便的 API 檔案 功能,我將在下一篇文章進行介紹.