在 Web 開發中,處理 HTTP 請求和資料驗證是不可或缺的環節。FastAPI 作為一個高效能的 Python Web 框架,與 Pydantic 的整合提供了一套簡潔且強大的解決方案。透過 Pydantic 的資料模型定義和驗證機制,開發者可以輕鬆處理各種資料型別,確保 API 的穩定性和可靠性。尤其在處理 POST 請求時,Pydantic 可以有效地解析和驗證請求體,簡化資料處理流程。此外,FastAPI 與 Pydantic 的結合也支援自動生成 API 檔案,提高開發效率。
使用POST方法克服GET方法的限制
在HTTP協定中,使用GET方法進行客戶端-伺服器互動存在某些缺點。首先,GET方法的安全性較低,因為URL及其引數資料會在瀏覽器的位址列中顯示。其次,GET請求所能傳送的資料量有限(通常只有幾千位元組),並且資料必須以ASCII字元表示,這意味著無法直接傳送二進位制資料(如圖片)。
為了建立新的資源,HTTP協定建議使用POST方法。POST請求將所需的資料封裝在請求體中,這樣不僅可以提高安全性(因為請求體不會顯示在瀏覽器的位址列中),還可以傳送大量資料,甚至包括二進位制資料。
使用Curl命令傳送POST請求
由於瀏覽器無法直接傳送POST請求,我們需要藉助其他工具,如Curl命令列工具。以下是一個典型的Curl POST命令示例:
curl -i -H "Content-Type: application/json" -X POST -d "{\"prodId\":\"1\",\"prodName\":\"Ceiling Fan\", \"price\":\"2000\", \"stock\":\"50\" }" http://localhost:8000/product
內容解密:
-i
引數用於顯示HTTP頭資訊。-H "Content-Type: application/json"
指定了請求體的格式為JSON。-X POST
明確指定使用POST方法(預設是GET方法)。-d
後面跟隨的是JSON格式的資料,這些資料填充了HTTP請求體。
在FastAPI中使用POST方法
在FastAPI應用中,POST請求由 @app.post()
裝飾器處理。該裝飾器需要一個必備的路徑字串引數。ASGI伺服器將請求的上下文資料傳遞給定義在 @app.post()
下的操作函式,該函式包含請求物件和請求體資料。
Body引數的使用
from fastapi import FastAPI, Body
app = FastAPI()
@app.post("/product")
async def addnew(prodId: int = Body(), prodName: str = Body(), price: float = Body(), stock: int = Body()):
product = {'Product ID': prodId, 'product name': prodName, 'Price': price, 'Stock': stock}
return product
內容解密:
addnew
函式定義了四個Body引數:prodId
、prodName
、price
和stock
,它們是Body
類別的例項。- 當客戶端傳送POST請求到
/product
路徑時,addnew
函式會被呼叫,並將請求體中的資料指定給相應的Body引數。 - 函式傳回一個包含產品資訊的字典。
使用Pydantic進行資料建模
當函式定義有很多引數時,直接傳遞這些引數會變得很麻煩。使用Pydantic函式庫可以解決這個問題。Pydantic是一個用於資料建模、驗證和解析的函式庫,FastAPI廣泛使用Pydantic來宣告資料模型。
使用 BaseModel
定義資料模型
from pydantic import BaseModel
class Product(BaseModel):
prodId: int
prodName: str
price: float
stock: int
內容解密:
Product
類別繼承自BaseModel
,定義了產品的資料模型。- 該模型可以用於驗證和解析請求體中的資料。
使用 dataclasses
模組
Python的 dataclasses
模組(從3.7版本開始引入)提供了一種簡便的方式來建立資料容器類別。
from dataclasses import dataclass
@dataclass
class Product:
prodId: int
prodName: str
price: float
內容解密:
@dataclass
裝飾器自動為Product
類別生成__init__
建構函式和__repr__
方法,用於字串表示。- 這使得建立和操作
Product
物件變得更加方便。
Swagger UI測試POST請求
Swagger UI提供了一個方便的介面來測試FastAPI應用的路由。在Swagger UI中,可以填寫Body引數的值,並檢視伺服器的回應。
圖表翻譯:
此圖示展示瞭如何在Swagger UI中填寫Body引數並測試POST請求。
graph LR; A[客戶端] -->|傳送POST請求|> B[伺服器]; B -->|處理請求|> C[傳回回應]; C -->|顯示回應|> A;
圖表翻譯: 此圖示呈現了客戶端傳送POST請求到伺服器,伺服器處理請求後傳回回應,並最終將回應顯示給客戶端的過程。
綜上所述,使用POST方法可以克服GET方法的限制,並且透過FastAPI和Pydantic,可以方便地處理請求體中的資料。同時,利用Swagger UI,可以輕鬆測試和驗證應用的功能。
Pydantic 與 FastAPI 的整合應用:深入解析與實作
在現代軟體開發中,資料驗證和模型定義是至關重要的環節。Pydantic 作為一個強大的資料驗證函式庫,與 FastAPI 的結合為開發者提供了高效、靈活的資料處理方案。本文將探討 Pydantic 的核心功能及其在 FastAPI 中的應用,並透過例項展示其強大的資料處理能力。
Pydantic 的基本概念
Pydantic 是根據 Python 型別提示的資料驗證和解析函式庫。它提供了一種簡潔的方式來定義資料模型,並自動生成資料驗證邏輯。Pydantic 的核心是 BaseModel
類別,透過繼承該類別,開發者可以定義自己的資料模型。
使用 BaseModel
定義資料模型
from pydantic import BaseModel
class Product(BaseModel):
prodId: int
prodName: str
price: float
stock: int
在上述範例中,我們定義了一個 Product
模型,包含了四個屬性:prodId
、prodName
、price
和 stock
。Pydantic 會根據這些屬性的型別自動進行資料驗證。
資料模型的 JSON 表示
Pydantic 的 BaseModel
提供了 schema_json()
方法,可以將模型的結構以 JSON Schema 的形式呈現。
{
"title": "Product",
"type": "object",
"properties": {
"prodId": {"title": "Prodid", "type": "integer"},
"prodName": {"title": "Prodname", "type": "string"},
"price": {"title": "Price", "type": "number"},
"stock": {"title": "Stock", "type": "integer"}
},
"required": ["prodId", "prodName", "price", "stock"]
}
內容解密:
此 JSON Schema 描述了 Product
模型的結構,包括各屬性的型別和必要性。這對於 API 檔案的自動生成和資料驗證具有重要意義。
在 FastAPI 中使用 Pydantic 模型
FastAPI 原生支援 Pydantic 模型,可以直接將 Pydantic 模型作為請求體的引數型別。
定義 FastAPI 端點
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Product(BaseModel):
prodId: int
prodName: str
price: float
stock: int
@app.post("/product/")
async def addnew(product: Product):
return product
在這個範例中,addnew
函式接收一個 Product
型別的引數。FastAPI 會自動將請求體解析為 Product
模型,並進行資料驗證。
自動生成的 API 檔案
FastAPI 會根據 Pydantic 模型自動生成 API 檔案,包括請求體的 Schema 描述。
{
"prodId": 1,
"prodName": "Ceiling Fan",
"price": 2000,
"stock": 50
}
內容解密:
此範例展示瞭如何使用 Pydantic 模型作為 FastAPI 端點的引數。FastAPI 會自動處理請求體的解析和驗證,大大簡化了開發流程。
資料驗證與處理
Pydantic 的強大之處在於其自動化的資料驗證功能。當請求體被解析為 Pydantic 模型時,Pydantic 會自動檢查資料是否符合模型的定義。
修改價格屬性
@app.post("/product/")
async def addnew(product: Product):
dct = product.dict()
price = dct['price']
if price > 5000:
dct['price'] = price + price * 0.1
product.price = dct['price']
return product
在這個範例中,我們對價格大於 5000 的產品增加了 10% 的稅費。這展示瞭如何在 FastAPI 端點中對 Pydantic 模型的屬性進行修改和處理。
內容解密:
此範例說明瞭如何在 FastAPI 中存取和修改 Pydantic 模型的屬性。透過 dict()
方法,我們可以將模型轉換為字典,便於進行進一步的處理。
Pydantic 模型的進階組態
Pydantic 的 BaseModel
提供了一個 Config
類別,用於自訂模型的行為。
使用 Config
類別自訂模型
class Product(BaseModel):
prodId: int
prodName: str
price: float
stock: int
class Config:
schema_extra = {
"example": {
"prodId": 1,
"prodName": "Ceiling Fan",
"price": 2000,
"stock": 50
}
}
在這個範例中,我們使用 schema_extra
屬性提供了一個範例資料,這將顯示在自動生成的 API 檔案中。
ORM 模式
Pydantic 的 orm_mode
組態允許模型從 ORM 物件中建立。這對於與資料函式庫互動非常有用。
class Product(BaseModel):
prodId: int
prodName: str
price: float
stock: int
class Config:
orm_mode = True
SQLAlchemy ORM 模型
from sqlalchemy import Column, Integer, Float, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class ProductORM(Base):
__tablename__ = 'products'
prodId = Column(Integer, primary_key=True, nullable=False)
prodName = Column(String)
price = Column(Float)
stock = Column(Integer)
內容解密:
此範例展示瞭如何使用 Pydantic 的 orm_mode
組態與 SQLAlchemy ORM 模型結合。透過設定 orm_mode = True
,Pydantic 模型可以直接從 ORM 物件建立,實作了資料函式庫物件與 Pydantic 模型的無縫對接。
隨著 Python 生態系統的不斷發展,Pydantic 和 FastAPI 將繼續演進,提供更多強大的功能和更好的開發體驗。未來,我們可以期待更多的整合和創新,例如更深入的 ORM 支援、更豐富的驗證選項等。開發者應持續關注這些技術的發展,以保持競爭力並構建更優秀的應用程式。