Python Web Flask — Flask-RESTful簡易CRUD API製作

Sean Yeh
Python Everywhere -from Beginner to Advanced
14 min readJun 15, 2021
Banff National Park, Canada, photo by Sean Yeh

什麼是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的初始狀態,我們可以

  1. 把名字改為「HelloWorld」;
  2. 使用「GET」;
  3. 並且輸入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的基本使用方式,上面列出的程式碼還有很多優化的空間。大家有興趣可以試著優化程式碼。

--

--

Sean Yeh
Python Everywhere -from Beginner to Advanced

# Taipei, Internet Digital Advertising,透過寫作讓我們回想過去、理解現在並思考未來。並樂於分享,這才是最大贏家。