使用 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 檔案
功能,我將在下一篇文章進行介紹.