FastAPI 作為一個高效能的 Python Web 框架,在構建 API 方面展現出顯著優勢。其非同步特性、根據 Pydantic 的資料驗證以及自動化檔案生成能力,有效提升了開發效率。然而,較陡峭的學習曲線和相對有限的社群資源,也需要開發者額外投入時間和精力。
在實際應用中,FastAPI 適用於建構 Web API 和 RESTful API,處理表單、Cookie 和各種 HTTP 請求。其內建的例外處理機制和 JSON 編碼器,方便開發者管理 API 回應和錯誤處理。此外,FastAPI 也支援背景任務和非同步路徑操作,可應用於日誌記錄、稽核追蹤等非同步處理場景。對於大型專案,FastAPI 提供了模組化和結構化的開發方式,方便程式碼管理和維護,避免迴圈依賴等問題。
FastAPI 的實際應用
FastAPI 可以用於建構各種 API,包括 Web API、RESTful API 等。
FastAPI 的優點
FastAPI 的優點包括:
- 高效能:FastAPI 的效能非常高,適合於高流量的 API。
- 強大的型別系統:FastAPI 的型別系統非常強大,允許你定義複雜的資料結構。
- 自動 API 檔案生成:FastAPI 可以自動生成 API 檔案,節省了開發時間。
FastAPI 的缺點
FastAPI 的缺點包括:
- 學習曲線陡峭:FastAPI 的學習曲線陡峭,需要一定的時間和努力來學習。
- 資源有限:FastAPI 的資源有限,需要自己去尋找相關的資源和檔案。
內容解密:
上述內容介紹了 FastAPI 的基礎知識,包括其基本結構、型別系統、表單處理、Cookie 處理和 API 檔案生成等。同時,也介紹了 FastAPI 的實際應用、優點和缺點。透過這些內容,讀者可以瞭解 FastAPI 的基本概念和使用方法。
from fastapi import FastAPI, Form
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
username: str
password: str
@app.post("/login")
def login(user: User):
# 處理登入邏輯
return {"message": "登入成功"}
@app.post("/register")
def register(username: str = Form(...), password: str = Form(...)):
# 處理註冊邏輯
return {"message": "註冊成功"}
圖表翻譯:
此圖示為 FastAPI 的基本結構,包括路由、服務和模型。路由定義了 API 的路徑和方法,服務處理了 API 請求的邏輯,模型定義了 API 的資料結構。
flowchart TD A[路由] --> B[服務] B --> C[模型] C --> D[資料函式庫] D --> E[回應]
FastAPI 中的表單和 Cookie 處理
FastAPI 是一個現代化的 Python Web 框架,提供了強大的功能來處理表單和 Cookie。下面我們將探討如何使用 FastAPI 來處理表單和 Cookie。
處理表單
FastAPI 提供了 Form
函式來處理表單資料。以下是使用 Form
函式的示例:
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/ch01/login/")
def login(username: str = Form(...), password: str = Form(...)):
return {"username": username, "password": password}
在上面的示例中,username
和 password
是表單欄位,使用 Form
函式來處理。
處理 Cookie
FastAPI 提供了 Response
物件來處理 Cookie。以下是使用 Response
物件來設定 Cookie 的示例:
from fastapi import FastAPI, Response
app = FastAPI()
@app.post("/ch01/login/rememberme/create/")
def create_cookies(resp: Response, id: UUID, username: str = ''):
resp.set_cookie(key="userkey", value=username)
resp.set_cookie(key="identity", value=str(id))
return {"message": "remember-me tokens created"}
在上面的示例中,create_cookies
函式設定了兩個 Cookie:userkey
和 identity
。
取得 Cookie
FastAPI 提供了 Cookie
函式來取得 Cookie。以下是使用 Cookie
函式來取得 Cookie 的示例:
from fastapi import FastAPI, Cookie
app = FastAPI()
@app.get("/ch01/login/cookies")
def access_cookie(userkey: Optional[str] = Cookie(None), identity: Optional[str] = Cookie(None)):
cookies = {}
cookies["userkey"] = userkey
cookies["identity"] = identity
return cookies
在上面的示例中,access_cookie
函式取得了兩個 Cookie:userkey
和 identity
。
探索 FastAPI 核心功能
在前一章中,我們瞭解瞭如何使用 FastAPI 框架輕鬆地建立 REST APIs。處理請求、Cookie 和表單資料是 FastAPI 的強項,建立不同的 HTTP 路徑操作也很簡單。
為了進一步瞭解框架的功能,本章將引導我們如何升級 REST APIs。這包括一些可以幫助最小化未經檢查的異常、JSON 編碼器可以直接管理端點回應、背景工作可以建立稽核跟蹤和日誌,以及多個執行緒可以與 uvicorn 的主執行緒一起執行的 API 方法。另外,本章還將解決管理來原始檔、模組和套件以進行大型企業專案的問題。
本章將使用一個智慧旅遊系統原型來協助闡述和示範 FastAPI 的核心模組。根據上述功能,本章將討論以下主要概念,以幫助我們擴充套件對框架的瞭解:
- 結構化和組織大型專案
- 管理 API 相關異常
- 將物件轉換為 JSON 相容型別
- 管理 API 回應
- 建立背景程式
- 使用非同步路徑操作
- 將中介軟體應用於過濾路徑操作
技術要求
本章將實作一個智慧旅遊系統的原型,旨在提供預訂資訊和關於旅遊景點的預訂。它可以提供使用者詳細資訊、旅遊景點詳細資訊和位置網格。它還允許使用者或旅客對旅遊進行評論和評分。原型具有管理員帳戶,用於新增和刪除所有旅遊詳細資訊、管理使用者和提供一些列表。該應用程式不會使用任何資料函式倉管理系統,因此所有資料都儲存在記憶體中。
結構化和組織大型專案
在 FastAPI 中,大型專案是透過組態和目的來組織和結構化的。專案應該始終保持靈活和可擴充套件,以適應額外的功能和要求。每個元件必須對應一個套件,具有多個模組,相當於 Flask 框架中的藍圖。
在這個智慧旅遊系統原型中,應用程式具有多個模組,例如登入、管理、存取、目的地和反饋相關功能。其中兩個最關鍵的是存取模組,負責管理所有使用者的旅行預訂,和反饋模組,允許客戶發布他們在每個目的地的體驗反饋。這些模組應該與其他模組分開,因為它們提供核心交易。
每個套件包含所有模組,其中實作了 API 服務和一些依賴項。所有上述模組現在都有自己的套件,使得測試、除錯和擴充套件應用程式變得容易。測試 FastAPI 元件將在未來的章節中討論。
重要注意事項
FastAPI 不需要在每個 Python 套件中新增 __init__.py
檔案,與 Flask 不同。但是,在佈署應用程式到倉函式庫時,必須排除 __pycache__
資料夾,因為它可能佔用大量空間。
實作 API 服務
為了使這些模組套件正常工作,main.py
檔案必須透過 FastAPI 例項呼叫和註冊所有它們的 API 實作。套件內的指令碼已經是 REST API 實作的微服務,除了它們是由 FastAPI 建立的。APIRouter
也具有相同的路徑操作、查詢和請求引數設定、表單資料處理、回應生成和引數注入模型物件。
但是,APIRouter
缺乏對例外處理程式、middleware 宣告和自定義的支援。
from fastapi import APIRouter
from login.user import Signup, User, Tourist, pending_users, approved_users
router = APIRouter()
@router.get("/ch02/admin/tourists/list")
def list_all_tourists():
return approved_users
這裡的 list_all_tourists()
API 方法操作是 admin
套件中的 manager.py
模組的一部分,使用 APIRouter
實作,由於專案結構化。該方法傳回允許存取應用程式的旅客記錄列表,可以由 login
套件中的 user.py
模組提供。
結構化大型FastAPI專案
在構建大型FastAPI專案時,保持良好的結構和組織至關重要。這涉及將程式碼分成多個模組和包,以便於維護和擴充套件。讓我們深入探討如何實作這一點。
模組之間的依賴
當構建大型專案時,模組之間的依賴關係會變得更加複雜。例如,在更新旅遊目的地的程式碼中,我們需要從destination.py
中匯入Tour
、TourBasicInfo
和TourLocation
模型類別。
from fastapi import APIRouter, status
from places.destination import Tour, TourBasicInfo, TourInput, TourLocation, tours, tours_basic_info, tours_locations
router = APIRouter()
@router.put("/ch02/admin/destination/update", status_code=status.HTTP_202_ACCEPTED)
def update_tour_destination(tour: Tour):
try:
tid = tour.id
tours[tid] = tour
tour_basic_info = TourBasicInfo(id=tid, name=tour.name, type=tour.type, amenities=tour.amenities, ratings=tour.ratings)
tour_location = TourLocation(id=tid, name=tour.name, city=tour.city)
tours_basic_info[tid] = tour_basic_info
tours_locations[tid] = tour_location
return {"message": "tour updated"}
except:
return {"message": "tour does not exist"}
避免迴圈依賴
在使用from... import
陳述式時,需要避免迴圈依賴。迴圈依賴發生在模組A匯入模組B的元件,而模組B又匯入模組A的資源物件。FastAPI不接受這種情況,會發出錯誤訊息。
實作主應用程式
最後,讓我們實作主應用程式main.py
。這個檔案使用FastAPI建立和註冊元件,以及包的模組。FastAPI類別有一個include_router()
方法,可以新增路由器並將其注入框架,使其成為專案結構的一部分。
from fastapi import FastAPI, Request
from admin import manager
from login import user
from feedback import post
from places import destination
from tourist import visit
app = FastAPI()
# 匯入路由器
app.include_router(manager.router)
app.include_router(user.router)
app.include_router(post.router)
app.include_router(destination.router)
app.include_router(visit.router)
透過這種方式,可以保持專案的結構清晰,方便維護和擴充套件。同時,也可以避免迴圈依賴,保證專案的穩定性和可靠性。
管理 API 相關異常
在 FastAPI 框架中,當 API 服務遇到執行期問題時,會傳回預設的 JSON 回應。然而,開發者可以選擇覆寫這些預設的例外處理機制,以自定義傳回的回應。
預設例外處理機制
FastAPI 框架繼承自 Starlette 工具包的預設例外處理機制,當遇到 HTTPException 時,會傳回預設的 JSON 回應。例如,當使用者登入時未提供使用者名稱和密碼,會傳回預設的 JSON 回應,如下圖所示:
預設異常結果
在某些情況下,框架可能會傳回 HTTP 回應狀態程式碼,而不是預設的 JSON 內容。然而,開發者可以選擇覆寫這些預設的例外處理機制,以自定義傳回的回應。
自定義例外處理機制
一種管理 API 服務例外處理機制的方法是使用 try-except 區塊來管理 API 的傳回回應。當 API 遇到異常時,可以傳回單一狀態碼,通常是 200 狀態碼。FastAPI 的路由操作和 APIRouter 有一個 status_code 引數,可以用來指示傳回的狀態碼。
狀態碼
狀態碼是 HTTP 回應的 3 位數字,表示 HTTP 回應的原因、資訊或狀態。200-299 範圍表示成功回應,300-399 範圍表示重定向,400-499 範圍表示使用者端問題,500-599 範圍表示伺服器錯誤。
範例
以下是使用 try-except 區塊和 status_code 引數來管理 API 服務例外處理機制的範例:
from fastapi import APIRouter, status
@router.put("/ch02/admin/destination/update", status_code=status.HTTP_202_ACCEPTED)
def update_tour_destination(tour: Tour):
try:
tid = tour.id
tours[tid] = tour
tour_basic_info = TourBasicInfo(id=tid, name=tour.name, type=tour.type, amenities=tour.amenities, ratings=tour.ratings)
tour_location = TourLocation(id=tid, name=tour.name, city=tour.city,
# ...
except Exception as e:
# ...
在這個範例中,當 API 遇到異常時,會傳回 202 狀態碼,表示接受但尚未處理完成。開發者可以自定義傳回的回應,以適應不同的需求。
圖表翻譯:
graph LR A[API 服務] --> B[try-except 區塊] B --> C[傳回單一狀態碼] C --> D[自定義傳回回應] D --> E[覆寫預設例外處理機制]
這個圖表顯示了 API 服務例外處理機制的流程,從 try-except 區塊到傳回單一狀態碼,然後到自定義傳回回應,最後到覆寫預設例外處理機制。
REST API 服務的狀態碼管理
在設計 REST API 服務時,狀態碼的管理是一個非常重要的方面。狀態碼可以告訴使用者端請求的結果是否成功,以及如果失敗,錯誤的原因是什麼。FastAPI 框架提供了多種方式來管理狀態碼,包括使用 status_code
引數和 JSONResponse
類別。
使用 status_code
引數
在 FastAPI 中,可以使用 status_code
引數來設定路由函式的傳回狀態碼。例如:
from fastapi import FastAPI, status
app = FastAPI()
@app.get("/ch02/admin/destination/list", status_code=200)
def list_all_tours():
return tours
在這個例子中,list_all_tours
函式的傳回狀態碼被設定為 200,表示請求成功。
使用 JSONResponse
類別
如果需要在 try-except 區塊中傳回不同的狀態碼,可以使用 JSONResponse
類別。JSONResponse
類別可以用來渲染 JSON 格式的傳回值,並且可以設定傳回的狀態碼。例如:
from fastapi.responses import JSONResponse
@app.post("/ch02/admin/destination/add")
def add_tour_destination(input: TourInput):
try:
#...
return JSONResponse(content={"message": "tour added"}, status_code=201)
except Exception as e:
return JSONResponse(content={"message": "error"}, status_code=400)
在這個例子中,add_tour_destination
函式的傳回值被設定為 JSON 格式,並且可以設定傳回的狀態碼。
多個狀態碼
如果需要在 try-except 區塊中傳回多個不同的狀態碼,可以使用 JSONResponse
類別,並且設定不同的狀態碼。例如:
from fastapi.responses import JSONResponse
@app.post("/ch02/admin/destination/add")
def add_tour_destination(input: TourInput):
try:
#...
return JSONResponse(content={"message": "tour added"}, status_code=201)
except ValueError as e:
return JSONResponse(content={"message": "invalid input"}, status_code=400)
except Exception as e:
return JSONResponse(content={"message": "error"}, status_code=500)
在這個例子中,add_tour_destination
函式的傳回值被設定為 JSON 格式,並且可以設定傳回的狀態碼,根據不同的異常型別。
處理HTTP異常的方法
在FastAPI中,處理HTTP異常是非常重要的。異常可以是由於使用者端的錯誤,例如傳入的資料格式不正確,或是伺服器端的錯誤,例如資料函式庫連線失敗。FastAPI提供了多種方法來處理HTTP異常,包括使用try-except區塊、raise HTTPException以及自訂異常。
使用try-except區塊
try-except區塊可以用來捕捉和處理異常。以下是範例:
try:
# 執行可能會發生異常的程式碼
tour_json = jsonable_encoder(tour)
return JSONResponse(content=tour_json, status_code=status.HTTP_201_CREATED)
except:
# 處理異常
return JSONResponse(content={"message": "invalid tour"}, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
在這個範例中,try區塊執行可能會發生異常的程式碼,如果發生異常,則會跳到except區塊處理。
raise HTTPException
HTTPException是FastAPI的一個類別,可以用來丟擲HTTP異常。以下是範例:
from fastapi import HTTPException, status
if approved_users.get(touristId) == None:
raise HTTPException(status_code=500, detail="details are missing")
在這個範例中,如果approved_users
中沒有找到touristId
,則會丟擲HTTPException,狀態碼為500,錯誤訊息為"details are missing"。
自訂異常
自訂異常可以用來處理商業邏輯相關的問題。以下是範例:
from fastapi import FastAPI, Request, status, HTTPException
class PostFeedbackException(HTTPException):
def __init__(self, detail: str, status_code: int):
super().__init__(status_code=status_code, detail=detail)
在這個範例中,定義了一個自訂異常PostFeedbackException
,繼承自HTTPException。這個異常可以用來處理與釋出評價相關的問題。
自訂例外處理機制
在 FastAPI 中,例外處理是一個非常重要的功能,可以幫助我們更好地管理 API 的錯誤和異常。下面,我們將探討如何在 FastAPI 中實作自訂例外處理機制。
自訂異常類別
首先,我們需要定義自訂異常類別,繼承自 HTTPException
。這些類別將包含 status_code
和 detail
屬性,分別代表 HTTP 狀態碼和錯誤詳細資訊。
from fastapi import HTTPException
class PostRatingException(HTTPException):
def __init__(self, detail: str, status_code: int):
self.status_code = status_code
self.detail = detail
class PostFeedbackException(HTTPException):
def __init__(self, detail: str, status_code: int):
self.status_code = status_code
self.detail = detail
自訂例外處理器
接下來,我們需要定義自訂例外處理器,使用 @app.exception_handler()
裝飾器將其對映到相應的異常類別。處理器函式應該接受 Request
和異常例項作為引數,並傳回一個 JSON 回應,包含錯誤詳細資訊和狀態碼。
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(PostFeedbackException)
def feedback_exception_handler(req: Request, ex: PostFeedbackException):
return JSONResponse(
status_code=ex.status_code,
content={"message": f"error: {ex.detail}"}
)
@app.exception_handler(PostRatingException)
def rating_exception_handler(req: Request, ex: PostRatingException):
return JSONResponse(
status_code=ex.status_code,
content={"message": f"error: {ex.detail}"}
)
異常觸發
當路由操作引發異常時,對應的例外處理器將被觸發,生成一個包含錯誤詳細資訊和狀態碼的 JSON 回應。
from handlers import PostRatingException, PostFeedbackException
@router.post("/feedback/add")
def post_tourist_feedback(touristId: UUID, tid: UUID, post: Post, bg_task: BackgroundTasks):
if approved_users.get(touristId) is None and tours.get(tid) is None:
raise PostFeedbackException("Invalid tourist or tour", 400)
在這個例子中,當 post_tourist_feedback
路由操作引發 PostFeedbackException
時,feedback_exception_handler
函式將被觸發,生成一個包含錯誤詳細資訊和狀態碼 400 的 JSON 回應。
更新評價系統
評價系統是任何旅遊平臺的重要組成部分,讓使用者可以對旅遊體驗進行評價和反饋。下面是更新評價系統的實作細節。
從技術架構視角來看,FastAPI 以其高效能和強大的型別系統為構建高效能 Web API 提供了堅實的基礎。本文深入探討了 FastAPI 的核心功能,包括表單和 Cookie 處理、異常管理、狀態碼管理以及大型專案的結構化,並以智慧旅遊系統原型為例,展示了 FastAPI 在實際應用中的優勢。然而,FastAPI 的學習曲線較陡峭,需要開發者投入一定的時間和精力來掌握。此外,社群資源相對有限,開發者可能需要更多地依賴官方檔案。儘管存在這些限制,FastAPI 的效能優勢和開發效率使其成為構建現代 Web API 的一個極具吸引力的選擇。對於追求高效能和開發效率的團隊,FastAPI 值得深入研究和應用。隨著社群的發展和資源的豐富,FastAPI 的應用前景將更加廣闊。玄貓認為,FastAPI 代表了 Web API 開發的一個重要趨勢,值得技術團隊密切關注並積極探索其在不同場景下的應用潛力。