在 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引數:prodIdprodNamepricestock,它們是 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 模型,包含了四個屬性:prodIdprodNamepricestock。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 支援、更豐富的驗證選項等。開發者應持續關注這些技術的發展,以保持競爭力並構建更優秀的應用程式。