快速入門 基于Flask實現Restful風格API

使用POSTMAN測試

早在一個筆記應用引出的全棧工程師的能力鍛煉這篇文章中我就提到過應該盡量去編寫API來實現一個web應用,在此之前也使用PHP實現了一個小的demo(具體參見用php實現一個app的API)。事實證明,越來越多的設備進入互聯網(物聯網時代的到來),我們需要更加優秀和耐用的API。于是,時隔半年,這一次我來展現給大家如何使用python的微框架flask,快速的實現一個Restful風格的API。

為什么是Restful?
必須有一種統一的機制,方便不同的前端設備與后端進行通信。這導致API構架的流行,RESTful API是目前比較成熟的一套互聯網應用程序的API設計理論。

工作原理

額,工作原理就是,客戶端發送request,服務端response一個json對象。

Restful Url的要求和在flask中的實現

在RESTful架構中,每個網址代表一種資源(resource),所以網址中不能有動詞,只能有名詞,而且所用的名詞往往與數據庫的表格名對應。一般來說,數據庫中的表都是同種記錄的"集合"(collection),所以API中的名詞也應該使用復數。

舉個例子:比如我們有一個數據資源,是一種對編程語言的描述,大概如下:

datas = [{'name': 'javascript', 'useto': 'web development'},
    {'name': 'python', 'useto': 'do anything'},
    {'name': 'php', 'useto': 'web development'},
    {'name': 'c++', 'useto': 'web server'}]

上面定義了一個數組,數組內包含了一些字典,每一個數組元素其實就是對某一種編程語言的簡單描述。

當我們要獲取數據集合的時候就可以這么請求:
https://myservice.com/api/v1/languages
當我們要獲取一條數據的詳細信息的時候,可以這么請求:
https://myservice.com/api/v1/languages/python

請求的方法 (解釋了為什么RestfulAPI的url里面沒有動詞)

我覺得你應該受夠了類似于下列的請求url了:
http://test.com/getstudents.do
http://test.com/getinfobyid.action
http://test.com/updateinfobyid.action
說實話,這樣的url我也很討厭。所以我用REST呀!
RestFul對于資源的具體操作類型,由HTTP動詞表示。
常用的HTTP動詞有下面五個。

GET(SELECT):從服務器取出資源(一項或多項)。
POST(CREATE):在服務器新建一個資源。
PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源)。
PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。
DELETE(DELETE):從服務器刪除資源。

恩,相同的url,執行不同的動作,得到的結果是不同的,習慣了之后,你就會愛上這種設計。

如何實現 直接貼上代碼

首先,關于flask的知識,pocoo的文檔真心不錯,用上半個小時過一遍快速如么就基本能看懂下面的代碼了。

其次,下面的代碼對數據源(一個數組)進行了CRUD的操作,返回json對象。

json對象被封裝成兩種情況:

第一種帶數據和狀態信息的響應:

例如:

{
 "data": [
   {
     "name": "javascript",
     "useto": "web development"
   },
   {
     "name": "python",
     "useto": "do anything"
   },
   {
     "name": "php",
     "useto": "web development"
   },
   {
     "name": "c++",
     "useto": "web server"
   }
 ],
 "status": {
   "code": 200,
   "message": "OK all right."
 }
}

當需要獲取資源的時候,我們返回一個data對應一個數組,同時返回狀態信息

第二種僅僅包含狀態信息的響應:
{
  "status": {
    "code": 404,
    "message": "No result matched."
  }
}

當僅僅執行增加、刪除和修改操作的時候,用戶關心的只是操作時否成功,僅需要返回對應的Restful約定的狀態信息即可!

在下面代碼中,對函數的返回進行了簡單的封裝

下面代碼中的 fullResponsestatusResponse 來源于自定義的模塊 restfultools
fullResponse接受兩個參數,一個是自己定義的狀態字典,一個是數據集和(數組)
statusResponse僅僅接收一個自定義的狀態字典

Flask主程序, rest.py
from flask import Flask, request, jsonify
from restfultools import * #這個是我自己寫的一個簡單的數據封裝工具(裝B的描述)

app = Flask(__name__)

#這是數據源
datas = [{'name': 'javascript', 'useto': 'web development'},
    {'name': 'python', 'useto': 'do anything'},
    {'name': 'php', 'useto': 'web development'},
    {'name': 'c++', 'useto': 'web server'}]


#獲取所有的資源  注意我用了復數形式的url
@app.route('/languages')
def getAll():
    return fullResponse(R200_OK, datas)


#根據name獲取資源中的某一個
@app.route('/language/<string:name>')
def getOne(name): 
    result = [data for data in datas if data['name'] == name]
    if len(result) == 0:
        return statusResponse(R404_NOTFOUND)
    return fullResponse(R200_OK, result[0])
    

#POST請求,增加一項
@app.route('/language', methods=['POST'])
def addOne():
    request_data = request.get_json()
    if not 'name' in request_data or not 'useto' in request_data:
        return statusResponse(R400_BADREQUEST)
    name = request_data['name']
    useto = request_data['useto']
    datas.append({'name': name, 'useto': useto})
    return statusResponse(R201_CREATED)
    

#PUT,PATCH 更新資源
#按照RestFul設計:
#PUT動作要求客戶端提供改變后的完整資源
#PATCH動作要求客戶端可以只提供需要被改變的屬性
#在這里統一使用PATCH的方法
@app.route('/language/<string:name>', methods=['PUT', 'PATCH'])
def editOne(name):
    result = [data for data in datas if data['name'] == name]
    if len(result) == 0:
        return statusResponse(R404_NOTFOUND)
    request_data = request.get_json()
    if 'name' in request_data:
        result[0]['name'] = request_data['name']
    if 'useto' in request_data:
        result[0]['useto'] = request_data['useto']
    return statusResponse(R201_CREATED)


#DELETE刪除,沒什么好說的
@app.route('/language/<string:name>', methods=['DELETE'])
def delOne(name):
    result = [data for data in datas if data['name'] == name]
    if len(result) == 0:
        return statusResponse(R404_NOTFOUND)
    datas.remove(result[0])
    return statusResponse(R204_NOCONTENT)

自定義的工具模塊 restfultools.py
#-*- coding: UTF-8 -*-
from flask import jsonify

# define statu_dics here
R200_OK = {'code': 200, 'message': 'OK all right.'}
R201_CREATED = {'code': 201, 'message': 'All created.'}
R204_NOCONTENT = {'code': 204, 'message': 'All deleted.'}
R400_BADREQUEST = {'code': 400, 'message': 'Bad request.'}
R403_FORBIDDEN = {'code': 403, 'message': 'You can not do this.'}
R404_NOTFOUND = {'code': 404, 'message': 'No result matched.'}


def fullResponse(statu_dic, data):
    return jsonify({'status': statu_dic, 'data': data})


def statusResponse(statu_dic):
    return jsonify({'status': statu_dic})

關于flask的版本: 0.11
運行的方法和之前有一點點不同:

export FLASK_APP = rest.py
flask run

悄悄的告訴你 以前的方法也支持,不過不推薦!

最后:API開發工具推薦
PostMan : 一個google-chrome的插件
Json Formatter: 一個Json格式化工具 也是Google-Chrome插件

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,563評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,694評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,672評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,965評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,690評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,019評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,013評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,188評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,718評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,438評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,667評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,149評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,845評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,252評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,590評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,384評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內容

  • 一說到REST,我想大家的第一反應就是“啊,就是那種前后臺通信方式。”但是在要求詳細講述它所提出的各個約束,以及如...
    時待吾閱讀 3,446評論 0 19
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,830評論 18 139
  • 本文首載于 Gevin的博客 基于一些不錯的RESTful開發組件,可以快速的開發出不錯的RESTful API,...
    Gevin閱讀 11,955評論 6 111
  • 22年12月更新:個人網站關停,如果仍舊對舊教程有興趣參考 Github 的markdown內容[https://...
    tangyefei閱讀 35,207評論 22 257
  • 蝶爸蝶媽們: 您們好。 時光在雨季里穿行,來不及日日再見。我們真的在不知不覺里,走了一周。 ...
    小蝴蝶楊寧閱讀 344評論 0 1