使用適用於 Python 的 FastAPI 構建應用程序
已發表: 2022-11-29FastAPI 是一種快速且輕量級的 Web 框架,用於使用 Python 3.6 及更高版本構建現代應用程序編程接口。 在本教程中,我們將介紹使用 FastAPI 構建應用程序的基礎知識,您將了解為什麼它被提名為 2021 年最佳開源框架之一。
一旦您準備好開發您自己的 FastAPI 應用程序,您將無需尋找很遠的地方來託管它們。 Kinsta 的應用程序託管和數據庫託管服務提供了一個強大的 Python 平台即服務。
讓我們先學習基礎知識。
FastAPI的優勢
下面是 FastAPI 框架給項目帶來的一些優勢。
- 速度:顧名思義,FastAPI 是一個非常快速的框架。 它的速度可與 Go 和 Node.js 相媲美,後者通常被認為是構建 API 的最快選項之一。
- 易於學習和編碼: FastAPI 已經知道了製作可用於生產的 API 所需的幾乎所有內容。 作為使用 FastAPI 的開發人員,您不需要從頭開始編寫所有代碼。 只需幾行代碼,您就可以準備好部署的 RESTful API。
- 全面的文檔: FastAPI 使用 OpenAPI 文檔標準,因此可以動態生成文檔。 本文檔提供了有關 FastAPI 的端點、響應、參數和返回代碼的詳細信息。
- 錯誤更少的 API: FastAPI 支持自定義數據驗證,這允許開發人員構建錯誤更少的 API。 FastAPI 的開發人員吹噓該框架導致更少的人為錯誤——減少多達 40%。
- 類型提示: types 模塊是在 Python 3.5 中引入的。 這使您能夠聲明變量的
type
。 當聲明變量的類型時,IDE 能夠提供更好的支持並更準確地預測錯誤。
如何開始使用 FastAPI
要按照本教程開始使用 FastAPI,您需要先做幾件事。
確保您擁有程序員的文本編輯器/IDE,例如 Visual Studio Code。 其他選項包括 Sublime Text 和 Espresso。
讓您的 Python 應用程序及其實例在虛擬環境中運行是一種常見的做法。 虛擬環境允許不同的包集和配置同時運行,並避免因包版本不兼容而導致的衝突。
要創建虛擬環境,請打開終端並運行以下命令:
$ python3 -m venv env
您還需要激活虛擬環境。 執行此操作的命令將根據您使用的操作系統和 shell 而有所不同。 以下是許多環境的一些 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 是一個閃電般快速的異步服務器網關接口 (ASGI) Web 服務器,適用於 Python,非常適合開發。 要安裝 Uvicorn,請運行以下命令:
$ pip3 install "uvicorn[standard]"
安裝成功後,在項目的工作目錄中創建一個名為main.py的文件。 該文件將成為您的應用程序入口點。
一個快速的 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()
, 和@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 字典,如上面代碼片段的第六行所示。
使用類型提示
如果您使用 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
,您將看到一個包含所有端點、方法和模式的屏幕。
這種基於瀏覽器的自動 API 文檔由 FastAPI 提供,您無需執行任何其他操作即可利用它。
另一種基於瀏覽器的 API 文檔,也是由 FastAPI 提供的,是 Redoc。 要訪問 Redoc,請導航至http://localhost:8000/redoc
,您將在其中看到端點列表、方法及其各自的響應。
在 FastAPI 中設置路由
@app
裝飾器允許您指定路由的方法,例如@app.get
或@app.post
,並支持GET
、 POST
、 PUT
和DELETE
,以及不太常見的選項HEAD
、 PATCH
和TRACE
。
使用 FastAPI 構建您的應用程序
在本教程中,您將逐步使用 FastAPI 構建 CRUD 應用程序。 該應用程序將能夠:
- 創建用戶
- 讀取用戶的數據庫記錄
- 更新現有用戶
- 刪除特定用戶
要執行這些 CRUD 操作,您將創建公開 API 端點的方法。 結果將是一個可以存儲用戶列表的內存數據庫。
您將使用 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
。 這應該返回所有用戶的列表,如下所示:
在此階段,您的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
,並將新創建的user
追加(添加)到數據庫db
。 最後,端點返回新創建的用戶id
的 JSON 對象。
您將必須使用 FastAPI 提供的自動 API 文檔來測試您的端點,如上所示。 這是因為您無法使用網絡瀏覽器發出發布請求。 導航到http://localhost:8000/docs
以使用 SwaggerUI 提供的文檔進行測試。
刪除數據庫記錄
由於您正在構建一個 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
匹配到一個用戶,則刪除該用戶; 否則,將引發狀態代碼為 404 的HTTPException
。
更新數據庫記錄
您將創建一個端點來更新用戶的詳細信息。 可以更新的詳細信息包括以下參數: 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
)不為空,則更新它。 - 如果操作成功,則返回用戶 ID。
- 如果找不到用戶,則會引發狀態代碼為 404 的
HTTPException
異常和一條消息Could not find user with id: {id}
。
要測試此端點,請確保您的 Uvicorn 服務器正在運行。 如果它沒有運行,請輸入以下命令:
uvicorn main:app --reload
下面是測試的截圖。
概括
在本教程中,您了解了適用於 Python 的 FastAPI 框架,並親眼目睹了啟動和運行 FastAPI 支持的應用程序的速度有多快。 您學習瞭如何使用該框架構建 CRUD API 端點——創建、讀取、更新和刪除數據庫記錄。
現在,如果您想將 Web 應用程序開發提升到一個新的水平,請務必查看 Kinsta 的應用程序託管和數據庫託管平台。 與 FastAPI 一樣,它非常簡單。