1. 程式人生 > >Flask-Restful詳解

Flask-Restful詳解

Restful API規範

restful api是用於在前端與後臺進行通訊的一套規範。使用這個規範可以讓前後端開發變得更加輕鬆。以下將討論這套規範的一些設計細節。

協議:

採用http或者https協議。

資料傳輸格式:

資料之間傳輸的格式應該都使用json,而不使用xml

url連結:

url連結中,不能有動詞,只能有名詞。並且對於一些名詞,如果出現複數,那麼應該在後面加s

比如:獲取文章列表,應該使用`/articles/`,而不應該使用/get_article/

HTTP請求的方法:

  1. GET:從伺服器上獲取資源。
  2. POST:在伺服器上新建立一個資源。
  3. PUT:在伺服器上更新資源。(客戶端提供所有改變後的資料)
  4. PATCH:在伺服器上更新資源。(客戶端只提供需要改變的屬性)
  5. DELETE:從伺服器上刪除資源。

示例如下:

  • GET /users/:獲取所有使用者。
  • POST /user/:新建一個使用者。
  • GET /user/id/:根據id獲取一個使用者。
  • PUT /user/id/:更新某個id的使用者的資訊(需要提供使用者的所有資訊)。
  • PATCH /user/id/:更新某個id的使用者資訊(只需要提供需要改變的資訊)。
  • DELETE /user/id/:刪除一個使用者。

狀態碼:

狀態碼 原生描述 描述
200 OK 伺服器成功響應客戶端的請求。
400 INVALID REQUEST 使用者發出的請求有錯誤,伺服器沒有進行新建或修改資料的操作
401 Unauthorized 使用者沒有許可權訪問這個請求
403 Forbidden 因為某些原因禁止訪問這個請求
404 NOT FOUND 使用者傳送的請求的url不存在
406 NOT Acceptable 使用者請求不被伺服器接收(比如伺服器期望客戶端傳送某個欄位,但是沒有傳送)。
500 Internal server error 伺服器內部錯誤,比如出現了bug

Flask-Restful外掛

通過pip install flask-restful即可安裝。

如果使用Flask-Restful,那麼定義檢視函式的時候,就要繼承自flask_restful.Resource類,然後再根據當前請求的method來定義相應的方法。比如期望客戶端是使用get方法傳送過來的請求,那麼就定義一個get方法。類似於MethodView。示例程式碼如下:

from flask import Flask,render_template,url_for
from flask_restful import Api,Resource

app = Flask(__name__)
# 用Api來繫結app
api = Api(app)

class IndexView(Resource):
    def get(self):
        return {"username":"donghao"}

api.add_resource(IndexView,'/',endpoint='index')

注意事項:

  1. endpoint是用來給url_for反轉url的時候指定的。如果不寫endpoint,那麼將會使用檢視的名字的小寫來作為endpoint
  2. add_resource的第二個引數是訪問這個檢視函式的url,這個url可以跟之前的route一樣,可以傳遞引數。並且還有一點不同的是,這個方法可以傳遞多個url來指定這個檢視函式。

引數解析:

Flask-Restful外掛提供了類似WTForms來驗證提交的資料是否合法的包,叫做reqparse。以下是基本用法:

 

parser = reqparse.RequestParser()
parser.add_argument('username',type=str,help='請輸入使用者名稱')
args = parser.parse_args()

add_argument可以指定這個欄位的名字,這個欄位的資料型別等。以下將對這個方法的一些引數做詳細講解:

  1. default:預設值,如果這個引數沒有值,那麼將使用這個引數指定的值。
  2. required:是否必須。預設為False,如果設定為True,那麼這個引數就必須提交上來。
  3. type:這個引數的資料型別,如果指定,那麼將使用指定的資料型別來強制轉換提交上來的值。
  4. choices:選項。提交上來的值只有滿足這個選項中的值才符合驗證通過,否則驗證不通過。
  5. help:錯誤資訊。如果驗證失敗後,將會使用這個引數指定的值作為錯誤資訊。
  6. trim:是否要去掉前後的空格。

其中的type,可以使用python自帶的一些資料型別,也可以使用flask_restful.inputs下的一些特定的資料型別來強制轉換。比如一些常用的:

  1. url:會判斷這個引數的值是否是一個url,如果不是,那麼就會丟擲異常。
  2. regex:正則表示式。
  3. date:將這個字串轉換為datetime.date資料型別。如果轉換不成功,則會丟擲一個異常。

輸出欄位:

對於一個檢視函式,你可以指定好一些欄位用於返回。以後可以使用ORM模型或者自定義的模型的時候,他會自動的獲取模型中的相應的欄位,生成json資料,然後再返回給客戶端。這其中需要匯入flask_restful.marshal_with裝飾器。並且需要寫一個字典,來指示需要返回的欄位,以及該欄位的資料型別。示例程式碼如下:

class ProfileView(Resource):
    resource_fields = {
        'username': fields.String,
        'age': fields.Integer,
        'school': fields.String
    }

    @marshal_with(resource_fields)
    def get(self,user_id):
        user = User.query.get(user_id)
        return user

get方法中,返回user的時候,flask_restful會自動的讀取user模型上的username以及age還有school屬性。組裝成一個json格式的字串返回給客戶端。

重新命名屬性:

很多時候你面向公眾的欄位名稱是不同於內部的屬性名。使用 attribute可以配置這種對映。比如現在想要返回user.school中的值,但是在返回給外面的時候,想以education返回回去,那麼可以這樣寫:

resource_fields = {
    'education': fields.String(attribute='school')
}

預設值:

在返回一些欄位的時候,有時候可能沒有值,那麼這時候可以在指定fields的時候給定一個預設值,示例程式碼如下:

resource_fields = {
    'age': fields.Integer(default=18)
}

複雜結構:

有時候想要在返回的資料格式中,形成比較複雜的結構。那麼可以使用一些特殊的欄位來實現。比如要在一個欄位中放置一個列表,那麼可以使用fields.List,比如在一個欄位下面又是一個字典,那麼可以使用fields.Nested。以下將講解下複雜結構的用法:

class ProfileView(Resource):
    resource_fields = {
        'username': fields.String,
        'age': fields.Integer,
        'school': fields.String,
        'tags': fields.List(fields.String),
        'more': fields.Nested({
            'signature': fields.String
        })
    }