10分鐘,帶你用Python構建RESTful API 服務

1. 前言

上一篇文章,介紹了使用 Java + Spring Boot + MyBatis 構建 RESTful API 的詳細步驟;很多小夥伴表示,更願意用 Python 編寫 RESTful API 服務,希望我能寫一下

本篇將以 Python 開始介紹搭建 RESTful API 的流程 ,使用的技術棧是:Flask + flask-restful + flasgger

2. 安裝依賴

使用 Python 編寫 RESTful API 之前,我們需要先在虛擬環境內安裝對應的依賴

具體包含:

  • Flask- 基礎 Web 框架

  • flask_restful- Flask 的擴展,增加了對快速構建 REST API 的支持

  • flasgger- flask 支持的 Swagger UI,可以生成 API 接口文檔

# 安裝flask
pip3 install flask

# 安裝flask-restful
pip3 install flask-restful

# 安裝flasgger
# 注意:需要更新setuptools
pip3 install -U setuptools
pip3 install flasgger

# 管理數據庫的依賴
pip3 install flask_script
pip3 install flask_migrate

3. Hello World

首先,我們使用 Pycharm 創建一個 Flask Web 項目,初始化代碼如下:

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run()

從 flask_restful 文件中導入 Api、Resource 兩個類,使用上面的 app 對象,構建一個 api 對象,接着準備一個列表數據

from flask_restful import Api,Resource

app = Flask(__name__)

# 實例化一個 Api 對象,用來創建、管理 RESTful Api
api = Api(app)


# 準備一個列表數據
datas = [{'id': 1, 'name': 'xag', 'age': 18}, {'id': 2, 'name': 'xingag', 'age': 19}]

然後,利用 Flask 中的 CBV 模式,創建一個 Resource 類的子類,用於定義資源路由

這裏以 GET / POST 動作爲例,重寫 get、post 方法,並編寫內部邏輯,返回數據即可

class UserView(Resource):
    """
    通過繼承 Resource 來實現調用 GET/POST 等動作方法
    """
    def get(self):
        """
        GET 請求
        :return:
        """
        return {'code': 200, 'msg': 'success', 'data': datas}


    def post(self):
        # 參數數據
        json_data = request.get_json()

        # 追加數據到列表中
        new_id = len(datas)+1
        datas.append({'id':new_id,**json_data})

        # 返回新增的最後一條數據
        return {'code': 200, 'msg': 'ok', 'success': datas[new_id - 1]}

最後,使用 Api 的實例對象,將上面定義的資源,利用路徑,完全暴露出去

# 暴露接口出去
# 資源路由:UserView
# 路徑:/user
api.add_resource(UserView,'/user')

運行程序後,就可以拿 Postman 或 cURL 去測試接口了

4. 項目實戰

在實際項目開發中,數據結構、層級關係往往要複雜很多,我們需要對項目進行一次整合,按功能進行封裝,具體步驟如下:

第 1 步,編寫配置文件

新建一個配置文件 config.py,將數據庫( 以 Mysql 爲例 )的連接信息,包含:用戶名、密碼、端口號、數據庫名、連接驅動和 Swagger 的設置信息追加進去

# config.py
USERNAME = 'root'
PASSWORD = 'root'
HOSTNAME = "127.0.0.1"
PORT = '3306'
DATABASE = 'xag'

DIALECT = 'mysql'
DRIVER = 'pymysql'

# 連接數據的URI
DB_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)

SQLALCHEMY_DATABASE_URI = DB_URI

SQLALCHEMY_TRACK_MODIFICATIONS = True

SWAGGER_TITLE = "API"
SWAGGER_DESC = "API接口"
# 地址,必須帶上端口號
SWAGGER_HOST = "localhost:5000"

第 2 步,模型映射數據庫

創建一個模型類 Foo 繼承 SQLAlchemy 對象,使用  __tablename__ 指定生成數據表的名稱、然後新增幾個常用字段

# models.py
from exts import db

class Foo(db.Model):
    """
    模型,將映射到數據庫表中
    """
    __tablename__ = 'foo'

    # 主鍵ID
    id = db.Column(db.INTEGER, primary_key=True, autoincrement=True)
    # 名字
    name = db.Column(db.String(100), nullable=False)
    # 年齡
    age = db.Column(db.INTEGER)

接着,創建 manage.py 文件

顯式導入上面創建的 Foo 類,使用 flask_migrate 中的 Migrate 綁定 App 和數據庫,利用 flask_script 中的 Manager 實例去添加一個腳本命令

# manager.py
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager

from exts import db
from api_app import app
from models import Foo

manager = Manager(app)
migrate=Migrate(app, db)
manager.add_command('db', MigrateCommand)

if __name__ == '__main__':
    manager.run()

需要注意的是,Foo 模型必須顯式導入,否則沒法映射到數據庫中

最後,通過下面 3 個腳本命令,將模型映射到數據庫中

除了第一次需要生成遷移腳本外,後面映射數據庫,只需要執行後面兩個命令即可

# 初始化遷移文件
python3 manager.py db init

# 映射到文件
python3 manager.py db migrate

# 映射到數據庫
python3 manager.py db upgrade

打開 Navicat For Mysql,即可以看到剛剛映射過來的數據表及遷移表

第 3 步,創建資源路由

下面以創建列表查詢( GET )、單條記錄的查詢( GET )、更新( PUT )、新增( POST )、刪除( DELETE )爲例

flask_restful 中的 marshal_with 類可以作爲裝飾器,定義到動作函數上,指定要返回的字段;然後使用 SQLAlchemy ORM 操作數據庫,將數據直接進行返回

比如:返回獲取數據列表

# api_foo.py
from flask_restful import Resource, fields, marshal_with, request

class FooListApi(Resource):
    # 定義要返回的字段
    resource_fields = {
        'id': fields.Integer,
        'name': fields.String,
        'age': fields.String
    }

    # 裝飾器,定義返回數據
    @marshal_with(resource_fields)
    def get(self):
        """
        返回所有記錄
        :return:
        """
        # 查詢數據庫
        foos = db.session.query(Foo).all()
        return foos

對於新增一個對象( POST 動作)

# api_foo.py
class FooApi(Resource):
    def post(self):
        """
        創建一條記錄
        :return:
        """
        # 參數
        params = request.get_json()
        name = params.get("name")
        age = params.get("age")
        # 構建一個模型
        foo = Foo(name=name, age=age)

        # 加入到數據庫
        db.session.add(foo)
        db.session.commit()

        return success("新增一條記錄成功!")

第 4 步,返回數據統一化

爲了保證返回的數據結構一致,可以將返回碼、返回信息及數據進行一次封裝,通過jsonify進行格式化返回

# restful_utils.py
from flask import jsonify

class HttpCode(object):
    ok = 200
    un_auth_error = 401
    params_error = 400
    server_error = 500

def restful_result(code, message, data):
    return jsonify({"code": code, "message": message, "data": data or {}})

def success(message="", data=None):
    """
    正確返回
    :return:
    """
    return restful_result(code=HttpCode.ok, message=message, data=data)

第 5 步,暴露接口

使用 flask_restful 中的 Api 實例對象,將上面定義的資源路由暴露出去

#api_app.py
from flask_restful import Api

api = Api(app)

# 某一條記錄
api.add_resource(FooApi, '/api/v1/foo','/api/v1/foo/<int:id>')

# 所有記錄
api.add_resource(FooListApi, '/api/v1/foos')

第 6 步,自動生成接口文檔

Flask 中同樣可以利用 Swagger 自動生成接口幫助文檔

首先,從配置文件 config.py 中讀取配置,實例化 Swagger 對象

#api_app.py
from flasgger import Swagger

# API可視化管理
swagger_config = Swagger.DEFAULT_CONFIG

# 標題
swagger_config['title'] = config.SWAGGER_TITLE   
# 描述信息
swagger_config['description'] = config.SWAGGER_DESC
# Host    
swagger_config['host'] = config.SWAGGER_HOST    

# 實例化
swagger = Swagger(app,config=swagger_config)

然後,在資源路由的動作內新增 swagger 註釋內容,包含:請求方式、參數、響應數據、描述信息等

具體可以參考:http://editor.swagger.io/#/

以獲取某一條數據爲例:

class FooApi(Resource):

    resource_fields = {
        'id': fields.Integer,
        'name': fields.String,
        'age': fields.String
    }

    @marshal_with(resource_fields)
    def get(self, id):
        """獲取用戶信息
    ---
    schemes:
      - http
    parameters:
      - name: id
        in: path
        type: integer
        required: true
        default: 1
        description: 用戶id

    responses:
      200:
        description: 返回用戶信息
        examples:
                {
                    "id": 1,
                    "name": "xag",
                    "age":"18"
                }
    """
        foo = db.session.query(Foo).get(id)
        return foo

最後,運行項目,訪問下面的鏈接,即可以看到定義好的 RESTful API 服務了

http://localhost:5000/apidocs/#/

5. 最後

上面就是通過 Flask + flask_restful 單表實現 RESTful API 完整的流程了,項目中涉及的多表,只需要更改數據庫的邏輯操作就可以了

我已經將文中全部源碼上傳到後臺,關注公衆號後回覆「 rest 」即可獲得全部源碼

近期熱門:


由菜鳥學Python原班人馬打造的公衆號:【程序員GitHub】 ,現已上線。

專注於分享GitHub上有趣的資源包括:Python,Java,Go語言,前端學習等優質的學習資源分享程序員圈的新鮮趣事,熱門乾貨,職場感悟

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章