Python Web Flask — Flask-RESTful簡易CRUD API製作
什麼是API
API是 Application Programming Interface的縮寫,如果照字面上翻譯的話應該是「應用程式介面」的意思。然而這個翻譯對於理解這個字的意思似乎沒有發揮很大的作用。
以日常生活的例子來解釋的話,我們可以想像自己在一家餐廳吃中餐。當服務生來到你的面前替你點菜時,你提供服務生一些『資訊』(諸如一份義大利肉醬麵、一份奶油筆管麵、一盤凱撒沙拉及兩杯冰紅茶等等),服務生把你的『資訊』送給廚房。過一陣子,便從廚房裡面端出相對資訊的物品,一份義大利肉醬麵、一份奶油筆管麵、一盤凱撒沙拉及兩杯冰紅茶。從這個例子來看,API就像是服務生的角色,幫助我們傳遞資訊給廚房,並且從廚房取得相對資訊的物品。
間單的來說,API是一種程式,當你給它一些資訊之後,它會回應給你一些相對的資訊。例如Twitter搜尋的API,當你使用這個API搜尋相關推文,API接受了你的訊息,並且從Twitter資料庫中比對出符合搜尋條件的推文,並且把這些推文回傳給你。這個過程就是 API的運作方式。
我們再想想前面的餐廳廚房例子。如果這個廚房是中央廚房(廚房C),它提供給不只一家餐廳食物,所有的餐廳只要能夠跟這個廚方簽好合約,該廚房的服務生就會把食物運送到每個不同餐廳裡面。換句話說,如果你是食客,進入了你家附近的一家餐廳,而這家餐廳剛好跟這個廚房C簽約,當你在餐廳裡面點一份義大利肉醬麵、一份奶油筆管麵、一盤凱撒沙拉及兩杯冰紅茶時,服務生就會把廚房C提供的食物遞送到你的桌上。
這個概念用在網路上,就如當你在網路上訂房的時候(例如你想要入住麗晶酒店),不論你是在酒店的官網,或者是在旅遊平台、訂房平台上面查看訂房的狀況,這時候你看到的資訊,都是透過API從酒店的資料庫中取出來。透過這樣子的方式,網路上各個平台的資訊就可以快速地交換與流通,而不會因為每個網站與平台的設計架構不同而受到限制。你也可以說,就是因為有了API的發明,全球的網路才能像現在你看到的這樣蓬勃發展。
什麼是RESTful
REST是Representational State Transfer的縮寫,可以讓電腦與電腦之間可以溝通的標準化方式。在REST後面加上ful後,這個字從名詞轉變為形容詞,可以用來形容網路架構的開發風格,這種開發方式採用的是REST風格。
我們知道在HTTP Request 裡面有很多的方法(method),除了之前常看到的GET與POST以外,再加上PUT與DELETE,就剛好對應到資料庫的基本增刪改查的CRUD操作。
換言之,我們平常對於網頁應用程式時常會使用的CRUD(新增、讀取、更新以及刪除)方式,在RESTful下面會以POST、GET、PUT與DELETE表現。
由於RESTful API 充分地使用了GET、POST、PUT與DELETE等的 HTTP protocol。藉由這樣的方式,可以讓URL達到簡潔且直觀。
由下表可以看到,若以 RESTful API 風格開發的話,網址幾乎沒有什麼改變:
就是藉由唯一的 URL來定位資源,將動作隱藏在 HTTP 的方法裡面。
實作簡易版RESTful API
Flask-RESTful 是一個輕量級的Flask擴充套件,讓我們可以快速建立REST API。這個套件,可以與ORM資料庫一起使用。如果本身對於Flask熟悉的話,要上手這個套件並不難。
接下來我們要透過Flask-RESTful實際製作一個簡易版的RESTful API。
建立FLASK應用程式
在進行這個簡易版RESTful API前,需要先建立一個FLASK應用程式。
from flask import Flask
app = Flask(__name__)if __name__ == '__main__':
app.run()
上面是最基本的FLASK應用程式。完成應用程式後,要安裝Flask-RESTful套件。
安裝FLASK RESTFUL套件
使用pip指令,透過終端機安裝Flask-RESTful套件:
$ pip install flask-restful
匯入FLASK RESTFUL套件
套件安裝完畢之後,我們就可以將套件匯入我們的python程式中。請在from flask import Flask
後面加上:
from flask_restful import Resource, Api
在上面這一行,我們匯入了Resource與Api。Resource讓我們可以建立可以連接到 REST API的資源。
建立Api實體對象
Api則是可讓我們與資源進行連接。我們可以指定一個變數api給Api實體對象。
api = Api(app)
換句話說,在這裡我們將app透過Api( Api來自於前面 from flask_restful import Resource
段落)包裹起來,並且指定為api變數。
建立資源
在這裏採用class的方式建立一個名叫Helloworld的資源。這個資源需要繼承Resource( Resource同樣來自於前面 from flask_restful import Resource
段落)。
class Helloworld(Resource):
pass
在這個Class裡面,我們可以加上各種不同的方法。在此,先加入一個get方法。在這個方法裡面,我們返回一組「鍵」、「值」字典。這組字典,在Postman測試軟體裡面會得到一個JSON格式的資料。
class Helloworld(Resource):
def get(self):
return {'message':'hello world'}
連結資源
最後,我們要透過add_resource來將url這個資源連結起來。下面是連結Helloworld的方式:
api.add_resource(Helloworld, '/')
其中『’/’ 』為首頁(http://127.0.0.1:5000/)。
啟動
透過下面指令,啟動api應用程式。
$ python api.py
這時候,應用程式會啟動服務,等待request。
測試
我們可以透過Postman來對應用程式進行測試。Postman可以發送 request到網址 http://127.0.0.1:5000/ ,藉由這個方式就可以接觸到api應用程式。
開啟Postman軟體
下面是Mac版Postman軟體的首頁畫面。在這個畫面下,按下中間的「Create New」可以開始使用Postman。
按下「Create New」按鈕之後,會出現下面的對話窗。這時請選擇右上的「Collection」建立專案資料夾。
點選之後,我們會來到下面的畫面,左邊有個「New Collection」,就是我們建立的專案資料夾。
我們可以按下New Collection旁邊的「…」按鈕來修改專案資料夾的名稱(Rename)。我們就把它改名為「FlaskAPI」吧。
選擇『Add Request』建立一個request。
按下去『Add Request』之後,可以看到下面的畫面:
這是一個Request的初始狀態,我們可以
- 把名字改為「HelloWorld」;
- 使用「GET」;
- 並且輸入url「http://127.0.0.1:5000」
發送request請求
如下圖,當我們按下右邊藍色的『Send』按鈕,Postman 會發送request到左邊指定的 URL (http://127.0.0.1:5000)。
結果,我們會收到上面的一組JSON資料。這就是我們先前在Helloworld裡面返回的字典。
RESTful下的CRUD
接下來,我們要再進一步的使用前面的Flask應用程式,來製作簡單的RESTful CRUD API,一組可以用來新增、讀取、更新與刪除的RESTful API。
在一般的情況下,人們會先把資料存放在諸如MySQL的資料庫裡面,再透過程式連接資料庫以存取資料。在這裏,我們為了簡化程式碼,這個例子會直接把資料寫在Python檔案裡面的list串列。
大家可以從下面的FLASK應用程式開始。下面的應用程式裡,已經匯入了flask_restful套件,並且將app實體化並包裹入Api了。
from flask import Flaskfrom flask_restful import Api, Resourceapp = Flask(__name__)api = Api(app)if __name__ == '__main__':app.run()
首先我們要增加一個list串列(user_list),來存放user使用者資料:
user_list = []
建立User資源
與前面一樣,這裏採用class的方式建立一個名叫User的資源。這個資源需要繼承Resource。在User裡面,我們先建立四個空白方法(get、post、delete與put,每個方法後面都暫時加上pass)。接著,我們希望把會員們的名稱(username)儲存在 user_list裡面作為資料,因此我們要把username設為參數。結果如下:
class User(Resource): def get(self, username):
pass def post(self, username):
pass def delete(self, username):
pass def put(self, username):
pass
接著開始針對每個方法來撰寫對應的函式。
POST方法
這個方法可以將新增的資料傳入。從下面程式碼可以看出來,我們將username當作參數傳入,而email則寫在json裡面,作為JSON的值傳入user_list
。傳入後並且返回傳入的內容。
def post(self, username):
user = {
'username': username,
'email': request.get_json().get('email')
} user_list.append(user) return user
GET方法
這個方法可以取得資料中的某一個符合條件者。因此,我們先使用for迴圈巡迴整個user_list
查看所有的紀錄中是否存在我們想要取出的資料?也就是符合我們傳入的username這個條件。若存在該資料,就返回該資料的內容;反之,即返回「404找不到資料(username:None)」的結果。
def get(self, username):
for user in user_list:
if user['username'] == username:
return user
return {'username': None}, 404
DELETE方法
這個方法可以刪除資料。首先在user_list
中尋找符合條件的使用者資料,如果找到資料的話,即透過pop的方式將資料移除。
def delete(self, username):
for ind, user in enumerate(user_list):
if user['username'] == username:
deleted_user = user_list.pop(ind)
print(deleted_user)
return {'note': 'successfully delete'}
PUT方法
透過這個方法可以更新現有的資料。先給定一個變數user_find,並且先賦予None的值(user_find = None
)。這個變數要用來存放判斷是否找到符合條件的結果。變數設定完畢後,即可開始遍尋user_list
中尋找符合條件的使用者資料(使用for迴圈),如果找到了,就把結果指定給變數user_find。
並且,假使user_find不是None的話,就先把原來的資料從user_list
中刪除,並且重新賦予新的email值 (user_find['email'] = request.get_json().get('email')
)。最後再把user_find
加回去user_list
中。
def put(self, username):
user_find = None
for user in user_list:
if user['username'] == username:
user_find = user
if user_find:
user_list.remove(user_find)
user_find['email'] = request.get_json().get('email')
user_list.append(user_find)
return user_find
UserList Class
我們需要一個可以顯示所有會員列表的Class。因此,建立了一個UserList來呈現所有的會員列表資料。
class UserList(Resource):
"""會員列表 """
def get(self):
return {'user_list': user_list}
連結資源
最後,我們還需要使用 add_resource 將 url 與資源連結起來。透過下面方式我們連結了 User 與 UserList:
api.add_resource(User, '/user/<string:username>')
api.add_resource(UserList, '/users')
啟動
在終端機輸入下面指令啟動應用程式用以測試API。
$ python api.py
這時候,應用程式會啟動服務,等待request。
測試
我們一樣可以透過Postman來進行API的測試。
發送GET request
先執行get users,取得所有會員的列表:
由於目前沒有任何資料,所以返回的JSON中user_list為空白。
發送POST request
由於前面的測試結果user_list為空白,我們在此先使用POST來輸入資料。下圖,我們POST了一筆會員資料,包含會員的username與email。
以此類推,重複上面的步驟,我們再多輸入幾個會員。
接著,再測試一下get users,取得所有會員的列表:
這時候,我們的user_list裡面多了四筆資料。
發送PUT request
使用PUT,將會員的email修改。原本沒有tw的電子郵件,在尾端增加了tw。
發送DELETE request
可以試著使用DELETE刪除一筆會員。下面的例子中我們使用 http://127.0.0.1:5000/user/Alice
,來刪除會員Alice。按下Postman的Send按鍵後,下面會返回 「successful delete」的JSON資料。
發送GET request查看所有資料
最後,我們可以發送一個GET request來查看一下所有存在user_list裡面的資料:
查看結果,目前剩下三筆會員(少了會員Alice),並且會員中Lisa的email多了一個tw結尾。
結論
以上是RESTful API的基本使用方式,上面列出的程式碼還有很多優化的空間。大家有興趣可以試著優化程式碼。