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'