跳轉至

建立 2026-10-11 更新 2026-10-11

model_config 模型設定

model_config 是 Pydantic V2 用來調整模型行為的類別屬性,取代 V1 的內部 class Config。透過 ConfigDict 可以設定:是否允許多餘欄位、是否關閉型別轉換(嚴格模式)、物件是否可修改、賦值時是否重新驗證,以及自動產生欄位別名。本頁整理最常用的設定與適用情境。

怎麼設定 model_config?

from pydantic import BaseModel, ConfigDict


class User(BaseModel):
    model_config = ConfigDict(str_strip_whitespace=True, extra="forbid")

    name: str
    age: int


print(User(name="  Alice  ", age=30).name)  # Alice

model_config 會被子類別繼承,子類別可以再覆寫部分設定。適合把團隊共用設定做成一個基底類別:

from pydantic import BaseModel, ConfigDict


class AppModel(BaseModel):
    model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)


class Product(AppModel):  # 自動套用 AppModel 的設定
    name: str

最常用的設定有哪些?

設定 預設 作用
extra "ignore" 多餘欄位怎麼處理:"ignore" 忽略、"forbid" 報錯、"allow" 保留
strict False True 時關閉型別轉換,"3" 不能當 int
frozen False True 時物件不可修改,而且可以當 dict 的鍵
validate_assignment False True 時對屬性賦值也會驗證
str_strip_whitespace False 自動去除字串前後空白
alias_generator None 用函式自動產生別名,例如轉成 camelCase
validate_by_name False 有別名的欄位也可以用 Python 名稱傳入
from_attributes False 允許從一般物件(例如 ORM 物件)的屬性讀取資料
use_enum_values False 儲存 Enum 的值而不是 Enum 成員

什麼時候該用 extra="forbid"?

接收外部輸入時,extra="forbid" 可以抓出拼錯的欄位名稱。預設的 "ignore" 會悄悄丟掉 {"emial": ...} 這種錯字,導致欄位使用預設值卻沒人發現:

from pydantic import BaseModel, ConfigDict, ValidationError


class Settings(BaseModel):
    model_config = ConfigDict(extra="forbid")

    debug: bool = False


try:
    Settings(debgu=True)  # 拼錯
except ValidationError as e:
    print(e.errors()[0]["type"])  # extra_forbidden

嚴格模式(strict)適合什麼情況?

寬鬆模式會把 "123" 轉成 123,對讀取表單、環境變數很方便;但資料來源本來就有型別(例如內部服務之間的 JSON),型別不對就代表上游有 bug,這時嚴格模式更安全:

from pydantic import BaseModel, ConfigDict, Field, ValidationError


class Payment(BaseModel):
    model_config = ConfigDict(strict=True)

    amount: int
    note: str = Field(default="", strict=False)  # 單一欄位可以個別放寬


try:
    Payment(amount="100")
except ValidationError as e:
    print(e.errors()[0]["type"])  # int_type

也可以只在單次驗證時開啟:Payment.model_validate(data, strict=True)。

如何讓物件不可修改?

frozen=True 讓物件建立後不能修改,適合當作設定值或值物件(value object),也能放進 set 或當 dict 的鍵:

from pydantic import BaseModel, ConfigDict, ValidationError


class Point(BaseModel):
    model_config = ConfigDict(frozen=True)

    x: int
    y: int


p = Point(x=1, y=2)
try:
    p.x = 10
except ValidationError as e:
    print(e.errors()[0]["type"])  # frozen_instance

print({p: "origin-ish"}[Point(x=1, y=2)])  # 可以當 dict 的鍵

需要修改時,改用 p.model_copy(update={"x": 10}) 產生新物件。

怎麼讓整個模型自動使用 camelCase?

前端或外部 API 慣用 camelCase 時,用 alias_generator 搭配內建的 to_camel,不用每個欄位手寫 alias:

from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel


class ApiModel(BaseModel):
    model_config = ConfigDict(alias_generator=to_camel, validate_by_name=True)


class UserProfile(ApiModel):
    first_name: str
    last_login_at: str | None = None


u = UserProfile.model_validate({"firstName": "Alice", "lastLoginAt": "2026-10-11"})
print(u.first_name)                   # Alice
print(u.model_dump(by_alias=True))    # {'firstName': 'Alice', 'lastLoginAt': '2026-10-11'}

如何從 ORM 物件建立模型?

SQLAlchemy 等 ORM 回傳的是一般物件而不是 dict。開啟 from_attributes=True 後,model_validate 會讀取物件屬性:

from pydantic import BaseModel, ConfigDict


class UserRow:  # 模擬 ORM 物件
    def __init__(self):
        self.id = 1
        self.name = "Alice"
        self.password_hash = "xxx"


class UserOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    name: str


print(UserOut.model_validate(UserRow()))  # id=1 name='Alice'

相關資料