FastAPI是一個快速和輕量級的網路框架,用於使用Python 3.6及以上版本構建現代應用程式設計介面。在本教程中,我們將介紹用FastAPI構建應用程式的基礎知識,你將瞭解到為什麼它被提名為2021年最佳開源框架之一。
FastAPI的優勢
下面是FastAPI框架給專案帶來的一些優勢。
- 速度:顧名思義,FastAPI是一個非常快的框架。它的速度可與Go和Node.js相媲美,後者被普遍認為是構建API的最快選擇之一。
- 易於學習和編碼:FastAPI已經想好了你製作一個生產就緒的API所需要的幾乎一切。作為一個使用FastAPI的開發者,你不需要從頭開始編碼所有的東西。只需幾行程式碼,你就可以擁有一個準備好部署的RESTful API。
- 全面的文件:FastAPI使用OpenAPI文件標準,因此可以動態地生成文件。該文件提供關於FastAPI的端點、響應、引數和返回程式碼的詳細資訊。
- 具有較少錯誤的API:FastAPI支援自定義資料驗證,這使開發人員能夠以更少的錯誤構建API。FastAPI的開發者吹噓說,該框架導致了更少的人為錯誤–多達40%的錯誤。
- 型別提示:型別模組是在Python 3.5中引入的。這使你能夠宣告一個變數的
type
。當一個變數的型別被宣告時,IDE能夠提供更好的支援,並更準確地預測錯誤。
如何開始使用FastAPI
要遵循本教程並開始使用FastAPI,你需要先做幾件事。
確保你有一個程式設計師的文字編輯器/IDE,如Visual Studio Code。其他選擇包括Sublime Text和Espresso。
讓你的 Python 應用程式和它們的例項在虛擬環境中執行是一種常見的做法。虛擬環境允許不同的軟體包集和配置同時執行,並避免因軟體包版本不相容而產生衝突。
要建立一個虛擬環境,開啟你的終端並執行這個命令。
$ python3 -m venv env
你還需要啟用這個虛擬環境。做到這一點的命令將取決於你所使用的作業系統和外殼。下面是一些CLI啟用的例子,適用於一些環境:
# On Unix or MacOS (bash shell): /path/to/venv/bin/activate # On Unix or MacOS (csh shell): /path/to/venv/bin/activate.csh # On Unix or MacOS (fish shell): /path/to/venv/bin/activate.fish # On Windows (command prompt): \path\to\venv\Scripts\activate.bat # On Windows (PowerShell): \path\to\venv\Scripts\Activate.ps1
(一些認識Python的IDE也可以被配置為啟用當前的虛擬環境)。
現在,安裝FastAPI:
$ pip3 install fastapi
FastAPI是一個構建API的框架,但為了測試你的API,你需要一個本地的Web伺服器。 Uvicorn是一個用於Python的快如閃電的非同步伺服器閘道器介面(ASGI)網路伺服器,非常適合於開發。要安裝Uvicorn,執行這個命令:
$ pip3 install "uvicorn[standard]"
安裝成功後,在你專案的工作目錄下建立一個名為main.py的檔案。這個檔案將是你的應用程式的入口點。
在IDE中檢視一個基本的FastAPI專案
一個快速的FastAPI例子
你將通過快速設定一個示例端點來測試你的FastAPI安裝。在你的main.py檔案中,貼上以下程式碼,然後儲存該檔案:
# main.py from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"greeting":"Hello world"}
上面的片段建立了一個基本的FastAPI端點。下面是對每一行所做工作的總結:
from fastapi import FastAPI
: 你的API的功能是由FastAPI Python類提供的。app = FastAPI()
: 這將建立一個FastAPI例項。@app.get("/")
: 這是一個python裝飾器,向FastAPI指定它下面的函式負責處理請求。@app.get("/")
: 這是一個指定路由的裝飾器。這將在網站的路由上建立一個GET方法。然後,結果由封裝的函式返回。- 其他可能用於通訊的操作包括
@app.post()
,@app.put()
,@app.delete()
,@app.options()
,@app.head()
,@app.patch()
, and@app.trace()
.
在檔案目錄中,在你的終端執行以下命令來啟動API伺服器:
$ uvicorn main:app --reload
在這個命令中,main
是你的模組的名字。app
物件是你的應用程式的例項,並被匯入ASGI伺服器。 --reload
標誌告訴伺服器在你做任何改變時自動重新載入。
你應該在你的終端看到類似這樣的東西:
$ uvicorn main:app --reload INFO: Will watch for changes in these directories: ['D:\\WEB DEV\\Eunit\\Tests\\fast-api'] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [26888] using WatchFiles INFO: Started server process [14956] INFO: Waiting for application startup. INFO: Application startup complete.
在你的瀏覽器中,導航到 http://localhost:8000
,確認你的API正在工作。你應該看到 “Hello”。”World “作為一個JSON物件出現在頁面上。這說明用FastAPI建立一個API是多麼容易。你所要做的就是定義一個路由並返回你的Python字典,如上面片段的第6行所示。
網頁瀏覽器中的FastAPI Hello World應用程式
使用型別提示
如果你使用Python,你已經習慣於用基本的資料型別來註釋變數,如 int
, str
, float
, 和 bool
。然而,從 Python 3.9 版本開始,高階資料結構被引入。這使得你可以使用資料結構,如 dictionaries
, tuples
, 和 lists
。通過FastAPI的型別提示,你可以使用pydantic模型來構造你的資料模式,然後,使用pydantic模型進行型別提示,並從所提供的資料驗證中獲益。
在下面的例子中,我們用一個簡單的餐價計算器 calculate_meal_fee
來演示Python中型別提示的使用:
def calculate_meal_fee(beef_price: int, meal_price: int) -> int: total_price: int = beef_price + meal_price return total_price print("Calculated meal fee", calculate_meal_fee(75, 19))
注意,型別提示不會改變你的程式碼執行方式。
FastAPI互動式API文件
FastAPI使用Swagger UI來提供自動互動式API文件。要訪問它,請導航到 http://localhost:8000/docs
,你會看到一個螢幕,上面有你所有的端點、方法和模式。
Swagger UI的FastAPI的文件
這個自動的、基於瀏覽器的API文件是由FastAPI提供的,你不需要做任何其他事情就可以利用它。
另一個基於瀏覽器的API文件,也是由FastAPI提供的,是Redoc。要訪問Redoc,請導航到 http://localhost:8000/redoc
,在那裡你會看到你的端點、方法和它們各自的響應的列表。
Redoc的FastAPI的文件
在FastAPI中設定路由
@app
裝飾器允許你指定路由的方法,如 @app.get
or @app.post
,並支援 GET
, POST
, PUT
, and DELETE
,以及不太常見的選項:HEAD
, PATCH
, 和 TRACE
。
使用FastAPI構建你的應用程式
在本教程中,我們將指導你用FastAPI構建一個CRUD應用程式。該應用程式將能夠:
- 建立一個使用者
- 讀取一個使用者的資料庫記錄
- 更新一個現有的使用者
- 刪除一個特定的使用者
為了執行這些CRUD操作,你將建立暴露API端點的方法。其結果將是一個可以儲存使用者列表的記憶體資料庫。
用於CRUD示例的資料庫表結構
你將使用pydantic庫,使用Python型別註釋進行資料驗證和設定管理。為了本教程的目的,你將把你的資料的形狀宣告為帶有屬性的類。
本教程將使用記憶體中的資料庫。這是為了讓你快速開始使用FastAPI來構建你的API。然而,對於生產來說,你可以利用你選擇的任何資料庫,如PostgreSQL、MySQL、SQLite,甚至是Oracle。
構建應用程式
你將從建立你的使用者模型開始。該使用者模型將有以下屬性:
id
: 一個通用唯一識別符號(UUID)first_name
: 使用者的名字last_name
: 使用者的姓氏gender
: 使用者的性別roles
: 這是一個包含admin
和user
角色的列表
首先在你的工作目錄中建立一個名為models.py的新檔案,然後將以下程式碼貼上到models.py中,建立你的模型:
# models.py from typing import List, Optional from uuid import UUID, uuid4 from pydantic import BaseModel from enum import Enum from pydantic import BaseModel class Gender(str, Enum): male = "male" female = "female" class Role(str, Enum): admin = "admin" user = "user" class User(BaseModel): id: Optional[UUID] = uuid4() first_name: str last_name: str gender: Gender roles: List[Role]
在上面的程式碼中:
- 你的
User
類擴充套件了BaseModel
,然後從pydantic
匯入。 - 你定義了使用者的屬性,如上所述。
下一步是建立你的資料庫。用以下程式碼替換你的main.py檔案的內容:
# main.py from typing import List from uuid import uuid4 from fastapi import FastAPI from models import Gender, Role, User app = FastAPI() db: List[User] = [ User( id=uuid4(), first_name="John", last_name="Doe", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Jane", last_name="Doe", gender=Gender.female, roles=[Role.user], ), User( id=uuid4(), first_name="James", last_name="Gabriel", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Eunit", last_name="Eunit", gender=Gender.male, roles=[Role.admin, Role.user], ), ]
在main.py中:
- 你用
List
的型別初始化了db
,並傳入了User
模型 - 你建立了一個有四個使用者的記憶體資料庫,每個使用者都有必要的屬性,如
first_name
,last_name
,gender
, 和roles
。使用者Eunit
被分配了admin
和user
的角色,而其他三個使用者只被分配了user
的角色。
讀取資料庫記錄
你已經成功地建立了你的記憶體資料庫,併為其填充了使用者,所以下一步是建立一個端點,以返回所有使用者的列表。這就是FastAPI的作用。
在你的main.py檔案中,在你的 Hello World
端點下面貼上以下程式碼:
# main.py @app.get("/api/v1/users") async def get_users(): return db
這段程式碼定義了端點 /api/v1/users
,並建立了一個非同步函式get_users
,它返回資料庫db
的所有內容。
儲存你的檔案,你可以測試你的使用者端點。在你的終端執行以下命令來啟動API伺服器:
$ uvicorn main:app --reload
在你的瀏覽器中,導航到 http://localhost:8000/api/v1/users
。這應該會返回你所有使用者的列表,如下圖所示:
通過FastAPI資料庫讀取請求獲取的使用者資料
在這個階段,你的main.py檔案將看起來像這樣:
# main.py from typing import List from uuid import uuid4 from fastapi import FastAPI from models import Gender, Role, User app = FastAPI() db: List[User] = [ User( id=uuid4(), first_name="John", last_name="Doe", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Jane", last_name="Doe", gender=Gender.female, roles=[Role.user], ), User( id=uuid4(), first_name="James", last_name="Gabriel", gender=Gender.male, roles=[Role.user], ), User( id=uuid4(), first_name="Eunit", last_name="Eunit", gender=Gender.male, roles=[Role.admin, Role.user], ), ] @app.get("/") async def root(): return {"Hello": "World",} @app.get("/api/v1/users") async def get_users(): return db
建立資料庫記錄
下一步是建立一個端點,在你的資料庫中建立一個新的使用者。將下面的片段貼上到你的main.py檔案中:
# main.py @app.post("/api/v1/users") async def create_user(user: User): db.append(user) return {"id": user.id}
在這個片段中,你定義了提交新使用者的端點,並使用 @app.post
裝飾器來建立一個 POST
方法。
你還建立了函式 create_user
,它接受 user
模型的 User
,並將新建立的使用者追加(新增)到資料庫 db
中。最後,端點返回一個新建立的使用者的 id
的JSON物件。
你將不得不使用FastAPI提供的自動API文件來測試你的端點,如上所示。這是因為你不能使用網路瀏覽器進行釋出請求。導航到 http://localhost:8000/docs
,使用SwaggerUI提供的文件進行測試。
FastAPI POST請求的引數
刪除資料庫記錄
由於你正在建立一個CRUD應用程式,你的應用程式將需要具有刪除指定資源的能力。在本教程中,你將建立一個端點來刪除一個使用者。
將以下程式碼貼上到你的main.py檔案中:
# main.py from uuid import UUID from fastapi HTTPException @app.delete("/api/v1/users/{id}") async def delete_user(id: UUID): for user in db: if user.id == id: db.remove(user) return raise HTTPException( status_code=404, detail=f"Delete user failed, id {id} not found." )
下面是對這段程式碼的逐行分解:
@app.delete("/api/v1/users/{id}")
: 你使用@app.delete()
裝飾器建立了刪除端點。路徑仍然是/api/v1/users/{id}
,但隨後它檢索了id
,這是一個對應於使用者id的路徑變數。async def delete_user(id: UUID):
: 建立delete_user
函式,從URL中獲取id
。for user in db:
: 這告訴應用程式迴圈瀏覽資料庫中的使用者,並檢查所傳遞的id
是否與資料庫中的使用者相符。db.remove(user)
: 如果id
與使用者匹配,該使用者將被刪除;否則,將產生一個HTTPException
,狀態碼為404。
FastAPI DELETE請求的引數
更新資料庫記錄
你將建立一個端點來更新一個使用者的詳細資訊。可以更新的細節包括以下引數: first_name
, last_name
, 和 roles
。
在你的models.py檔案中,在你的 User
模型下貼上以下程式碼,也就是在 User(BaseModel):
類:
# models.py class UpdateUser(BaseModel): first_name: Optional[str] last_name: Optional[str] roles: Optional[List[Role]]
在這個片段中,UpdateUser
類擴充套件了 BaseModel
。然後,你將可更新的使用者引數,如 first_name
, last_name
, 和 roles
,設定為可選。
現在你將建立一個端點來更新一個特定使用者的詳細資訊。在你的main.py檔案中,在 @app.delete
裝飾器之後貼上以下程式碼:
# main.py @app.put("/api/v1/users/{id}") async def update_user(user_update: UpdateUser, id: UUID): for user in db: if user.id == id: if user_update.first_name is not None: user.first_name = user_update.first_name if user_update.last_name is not None: user.last_name = user_update.last_name if user_update.roles is not None: user.roles = user_update.roles return user.id raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}")
在上面的程式碼中,你已經做了以下工作:
- 建立
@app.put("/api/v1/users/{id}")
,即更新端點。它有一個變數引數id
,與使用者的id相對應。 - 建立了一個名為
update_user
的方法,它接收了UpdateUser
類和id
。 - 使用一個
for
迴圈來檢查與所傳id
相關的使用者是否在資料庫中。 - 檢查使用者的任何引數是否
is not None
(非空)。如果任何引數,如first_name
,last_name
, 或roles
,,不是null,那麼它就被更新。 - 如果操作成功,將返回使用者ID。
- 如果沒有找到使用者,就會產生一個
HTTPException
異常,狀態程式碼為404,資訊為Could not find user with id: {id}
的使用者。
要測試這個端點,確保你的Uvicorn伺服器正在執行。如果它沒有執行,請輸入這個命令:
uvicorn main:app --reload
下面是測試的螢幕截圖。
FastAPI UPDATE請求的引數
小結
在本教程中,你已經瞭解了Python的FastAPI框架,並親眼目睹瞭如何快速啟動和執行一個由FastAPI驅動的應用程式。你學會了如何使用該框架建立 CRUD API 端點 – 建立、讀取、更新和刪除資料庫記錄。
評論留言