教你一招!用Python和Flask創(chuàng)建REST API!


REST API 簡介
注意,這里只是對REST API 的簡單介紹,起到拋磚引玉作用,更加深入內(nèi)容不在本次學習范圍內(nèi),感興趣的小伙伴可以查看相關資料深入學習。此外本號接受該領域的投稿,歡迎聯(lián)系云朵君!

API
API,全名Application Programming Interface (應用程式介面),簡單來說,是品牌開發(fā)出的一種接口,讓第三方可以額外開發(fā)、應用在自身的產(chǎn)品上的系統(tǒng)溝通介面。
REST API
REST 是一種通過 HTTP 協(xié)議設計 API 的架構風格。它的主要優(yōu)點是其極大的靈活性。只要需要直接從服務器向 Web 應用程序或站點的用戶提供數(shù)據(jù),開發(fā)人員就會使用 REST API。
REST API 的主要組件:
客戶 — 在用戶端(在他的設備上)啟動的客戶端或程序啟動通信。 服務器 — 使用 API 訪問其功能和數(shù)據(jù)的服務器。 資源 — 服務器傳輸給客戶端的任何內(nèi)容(視頻、文本、圖片)。
REST API 通過 HTTP 請求進行通信,完成以下功能——創(chuàng)建、讀取、更新和刪除數(shù)據(jù)。它們也稱為 CRUD 操作。REST 提供有關請求資源的信息,并使用四種方法來描述如何處理資源:
POST — 創(chuàng)建資源; GET — 獲取資源; PUT — 更新資源; DELETE — 刪除資源。
RESTful API
REST,全名Representational State Transfer( 表現(xiàn)層狀態(tài)轉移),他是一種設計風格,RESTful 只是轉為形容詞,像是 peace 和平這名詞,轉成形容詞是peaceful,RESTful 則形容以此規(guī)范設計的API,稱為RESTful API。
RESTful API 主要由三種元件組成:
Nouns 名詞:定義資源位置的URL,每個資源在網(wǎng)路上都會有唯一的位置,就如每戶人家都有唯一的地址一樣。 Verbs 動詞:對資源要做的動作。 Content Types 資源呈現(xiàn)方式:API 資源可以以多種方式表現(xiàn),最常用的是JSON,輕量易處理。
所以使用 RESTful 風格設計的API,就有了以下幾種優(yōu)點及限制:
有唯一的URL表示資源位置,統(tǒng)一的API 接口。(Uniform Interface) 無狀態(tài)。(Stateless)
Restful API 它允許集成應用程序 app 或與 Restful Web 服務交互。它現(xiàn)在正在成長為連接微服務架構中組件的最常用方法。我們借助 API,能夠獲取或發(fā)送數(shù)據(jù)到網(wǎng)站并執(zhí)行一些操作,目的是通過 Web 服務完成我們的任務。每個網(wǎng)站都使用不同類型的 API,例如股票市場交易網(wǎng)站,借助 API 獲取當前價格和上下波動。
創(chuàng)建第一個 REST API
同樣,我們創(chuàng)建 Hello world API,它表示如果你對其發(fā)出 get 請求,將獲得 JSON 響應,一般情況下, API 給出 JSON 類型的響應。接下來,使用 pip 包管理器安裝 Flask:
pip install flask
pip install flask-restful
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class Helloworld(Resource):
def __init__(self):
pass
def get(self):
return {
"Hello": "World"
}
api.add_resource(Helloworld, '/')
if __name__ == '__main__':
app.run(debug=True)
ok,到現(xiàn)在已經(jīng)創(chuàng)建了第一個Rest api,看起來挺簡單的,那么,什么是Flask-Restful呢?
Flask restful 定義了資源Resource類,其中包含每個 HTTP 方法的方法。方法名稱應與其對應的 HTTP 方法相同,并以小寫形式書寫,如上代碼中所示。我們發(fā)現(xiàn)這些方法沒有路由裝飾器,這是它們是基于資源路由的。無論定義什么類,我們都可以使用添加資源add_resource方法定義到它的路由以及在對應路由上調(diào)用該類。
說明: 在上面的代碼中,我們首先加載需要的父類,然后初始化我們的app和API。之后,我們創(chuàng)建了一個程序,并且我們正在發(fā)出一個 GET 請求,說明如果有人點擊了這個程序,那么他將得到 Hello world 作為 JSON 格式的響應。要打開特定 URL,我們使用 add resource 方法并將其路由到默認斜杠。要運行此文件,可以使用 POSTMAN 工具(一種 API 維護工具)來創(chuàng)建、測試和管理 API。還可以使用requests請求模塊使用以下代碼測試此 API。首先,運行上面的文件,它會給你 localhost URL,然后在另一個命令提示符下,運行下面的代碼文件:
import requests
url = "http://127.0.0.1:5000/"
response = requests.get(url=url)
print(response.text)
{
"Hello": "World"
}
通過 Flask RESTApi 理解 HTTP 請求
通過以上內(nèi)容的學習,相比大家已經(jīng)對 REST API 有個初步印象。接下來我們將繼續(xù)探索使用 REST API 的不同 HTTP 方法,其中我們定義一個列表,該列表將以字典(JSON 對象)的形式存儲從服務器獲取的所有數(shù)據(jù)。這是很重要的,因為我們在項目中有不同的api來獲取數(shù)據(jù),而不是其他地方的數(shù)據(jù)。
首先創(chuàng)建一個 API,在其中創(chuàng)建 3 個名為 GET、POST 和 DELETE 的 HTTP 方法,并且在其中創(chuàng)建一個自定義 URL,當請求 POST 方法時,它將以 Name 作為輸入;在請求 GET 方法時,將名稱返回;在DELETE時,如果該名稱存在,我們將刪除該名稱,再次訪問它會給我們 NULL。
創(chuàng)建一個文件并編寫以下代碼:
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
data = []
class People(Resource):
def get(self):
for x in data:
if x['Data'] == name:
return x
return {'Data': None}
def post(self, name):
temp = {'Data': name}
data.append(temp)
return temp
def delete(self):
for ind, x in enumerate(data):
if x['Data'] == name:
temp = data.pop(ind)
return {'Note': 'Deleted'}
api.add_resource(People, '/Name/')
if __name__ == '__main__':
app.run(debug=True)
打開 POSTMAN API 工具并點擊每個 HTTP 方法請求。首先,當我們使用 post 請求Name時,它給了我們一個name。在獲取請求時,我們將返回name。它在刪除時被刪除,當再次將其取回時,它會給你返回 NULL。
結果如下



如何在 Flask REST API 中使用裝飾器
我們使用帶有 API 的裝飾器來監(jiān)控 IP 地址、cookie 等。我們將繼續(xù)學習如何使用帶有裝飾器的Flask API。裝飾器是一個將另一個函數(shù)作為參數(shù)并返回另一個函數(shù)的函數(shù)。也可以將其理解為在不改變或修改當前功能的情況下,為現(xiàn)有功能提供一些附加功能的功能。
這里我們創(chuàng)建一個新文件,我將通過創(chuàng)建兩個裝飾器來展示。在第一個文件中,編寫返回代碼執(zhí)行時間的外部時間函數(shù)。我們從 functools 模塊(用于高階 python 函數(shù)的標準模塊)導入應用于 wrapper 函數(shù)的 wrap 裝飾器 。它通過復制所有參數(shù)來更新包裝函數(shù)。
from flask import Flask
from flask_restful import Resource, Api
import datetime
from flask import request
from functools import wraps
app = Flask(__name__)
api = Api(app)
def time(function=None):
@wraps(function)
def wrapper(*args, **kwargs):
s = datetime.datetime.now()
_ = function(*args, **kwargs)
e = datetime.datetime.now()
print("Execution Time : {} ".format(e-s))
return _
return wrapper
class HelloWorld(Resource):
@monitor
def get(self):
return {"hello": "world"}
api.add_resource(HelloWorld, "/")
if __name__ == "__main__":
app.run(debug=True)
我們創(chuàng)建第二個裝飾器來監(jiān)視cookie和IP地址,因此創(chuàng)建下面的函數(shù)。不是向hello world函數(shù)添加時間裝飾器,而是添加監(jiān)視器裝飾器并運行代碼。
def monitor(function=None):
@wraps(function)
def wrapper(*args, **kwargs):
_ = function(*args, **kwargs)
print("Ip Address : {} ".format(request.remote_user))
print("Cookies : {} ".format(request.cookies))
print(request.user_agent)
return _
return wrapper
如何使 Flask API 更安全
當我們設計API時,我們也應該注意安全性,因為很多人會訪問它。因為API可能包含一些雙方之間的機密數(shù)據(jù),因此我們可以指定只有授權的人可以訪問API,那該怎么辦?此時可以使用Flask基本身份驗證。當然,此時需要使用pip命令安裝這個flask模塊。
pip install flask-httpauth
我們正在構建一個API并定義User數(shù)據(jù)字典,其中包含用戶名和密碼。當在實時用例中工作時,可以通過配置文件或從數(shù)據(jù)庫中接受用戶名和密碼。首先,我們創(chuàng)建一個主要函數(shù)來匹配用戶名和密碼,并創(chuàng)建一個GET方法,該方法表示任何點擊此API的人,如果沒有登錄,我們就無法訪問數(shù)據(jù)。
from flask import Flask
from flask_restful import Resource, Api
from flask_httpauth import HTTPBasicAuth
app = Flask(__name__)
api = Api(app, prefix="/api/v1")
auth = HTTPBasicAuth()
USER_DATA = {
"admin": "SuperSecretPwd"
}
#route to verify the password
@auth.verify_password
def verify(username, password):
if not(username and password):
return False
return USER_DATA.get(username) == password
class PrivateResource(Resource):
@auth.login_required
def get(self):
return {"How's the Josh": "High"}
api.add_resource(PrivateResource, '/private')
if __name__ == '__main__':
app.run(debug=True)
當我們使用POSTMAN運行上述文件時,我們會嘗試在沒有登錄的情況下獲取數(shù)據(jù),以便給你演示未經(jīng)授權的訪問權限。

現(xiàn)在轉到授權,并單擊Basic authorization。輸入用戶名和密碼,然后點擊GET請求以獲得所需的結果。

這是保護 Flask API 的方法,也是最基本的方法,當然還有更多更高級的方法,這里不做過多的介紹。
如何在 Flask API 上啟用跟蹤
至此我們已經(jīng)了解了如何保護我們的 API,在未經(jīng)授權的登錄禁止訪問,但是如果我們還想知道訪問者的位置(緯度和經(jīng)度點)、IP 地址、服務器名稱(例如訪問API 的人的詳細信息),我們還可以繼續(xù)配置,使用 REST API 的基本flask跟蹤應用程序。首先,使用 PIP 命令安裝flask跟蹤包。
pip install flask-track-usage
接下來看下該程序:
from flask import Flask, g
app = Flask(__name__)
app.config['TRACK_USAGE_USE_FREEGEOIP'] = False
app.config['TRACK_USAGE_INCLUDE_OR_EXCLUDE_VIEWS'] = 'include'
from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter
t = TrackUsage(app, [
PrintWriter(),
OutputWriter(transform=lambda s: "OUTPUT: " + str(s))
])
@t.include
@app.route('/')
def index():
g.track_var["optional"] = "Write_Something"
return "Hello"
#Run the application
if __name__ == "__main__":
app.run(debug=True)
該程序通過導入 Track Usage、Input writer 和 output writer 來創(chuàng)建一個跟蹤應用程序。將flask app傳遞給 Track 包并使用輸出編寫器,并使用 lambda 函數(shù)以字符串格式寫入輸出。之后在 slash 上創(chuàng)建一個基本路由,并將跟蹤應用程序作為裝飾器包含在內(nèi)。g 代表全局,表示數(shù)據(jù)在上下文中是全局的。因此,創(chuàng)建一個基本 API,它在瀏覽器返回"Hello",同時在后端獲得所有人員的信息。
如何為REST API編寫單元測試代碼
現(xiàn)在已經(jīng)為案例創(chuàng)建了一個不錯的REST API。盡管如此,我們還需要為REST API編寫單元測試代碼,因為從API中識別常見錯誤,并確保生產(chǎn)安全是至關重要的。
如下是創(chuàng)建一個名為run的新文件并開發(fā)以下簡單API。
from flask import Flask
from flask_restful import Resource, Api
import json
app = Flask(__name__)
api = Api(app)
class Helloworld(Resource):
def __init__(self):
pass
def get(self):
return json.dumps({"Message": "Fine"})
api.add_resource(Helloworld, '/')
if __name__ == '__main__':
app.run(debug=True)
現(xiàn)在創(chuàng)建另一個名為test的文件,在其中編寫用于對API進行單元測試的代碼。最常見的情況是執(zhí)行以下三個基本單元測試。
檢查響應碼是否為200 檢查從API編寫的內(nèi)容是否為應用程序JSON格式 檢查我們正在訪問的所有鍵是否都存在于API數(shù)據(jù)處理中
from run import app
import unittest
class FlaskTest(unittest.TestCase):
#Check for response 200
def test_inde(self):
tester = app.test_client(self) #tester object
response = tester.get("/")
statuscode = response.status_code
self.assertEqual(statuscode, 200)
#check if the content return is application JSON
def test_index_content(self):
tester = app.test_client(self)
response = tester.get("/")
self.assertEqual(response.content_type, "application/json")
#check the Data returned
def test_index_data(self):
tester = app.test_client(self)
response = tester.get("/")
self.assertTrue(b'Message' in response.data)
if __name__ == '__main__':
unittest.main()
如果你已經(jīng)學習過網(wǎng)絡爬蟲,你應該知道 200 響應意味著對特定 URL 的請求已成功發(fā)出,并返回響應。
好了,這就是本文的全部內(nèi)容。到這里我們已經(jīng)學會了從頭開始創(chuàng)建 Flask REST API ,并輕松安全地對其進行維護。
Flask 作為 Python Web 領域最為著名的輕量級 Web 開發(fā)框架,對于致力于 Web 開發(fā)的同學來說,掌握基本的 Flask 技能還是非常有必要的,你學會了嗎?
推薦閱讀:
入門: 最全的零基礎學Python的問題 | 零基礎學了8個月的Python | 實戰(zhàn)項目 |學Python就是這條捷徑
干貨:爬取豆瓣短評,電影《后來的我們》 | 38年NBA最佳球員分析 | 從萬眾期待到口碑撲街!唐探3令人失望 | 笑看新倚天屠龍記 | 燈謎答題王 |用Python做個海量小姐姐素描圖 |碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影
趣味:彈球游戲 | 九宮格 | 漂亮的花 | 兩百行Python《天天酷跑》游戲!
AI: 會做詩的機器人 | 給圖片上色 | 預測收入 | 碟中諜這么火,我用機器學習做個迷你推薦系統(tǒng)電影
小工具: Pdf轉Word,輕松搞定表格和水??! | 一鍵把html網(wǎng)頁保存為pdf!| 再見PDF提取收費! | 用90行代碼打造最強PDF轉換器,word、PPT、excel、markdown、html一鍵轉換 | 制作一款釘釘?shù)蛢r機票提示器! |60行代碼做了一個語音壁紙切換器天天看小姐姐!|
年度爆款文案
點閱讀原文,看B站我的20個視頻!

