第九章:特殊类型进阶
9.1 枚举 Enum
python
from enum import Enum
class Role(str, Enum): # 继承 str,序列化更友好
ADMIN = "admin"
USER = "user"
class Account(BaseModel):
name: str
role: Role
Account(name="小明", role="admin") # 字符串自动匹配枚举值9.2 Literal:限定只能是某几个值
python
from typing import Literal
class Request(BaseModel):
method: Literal["GET", "POST", "PUT", "DELETE"]
sort_order: Literal["asc", "desc"] = "asc"比枚举更轻量,IDE 还能自动补全可选值。
9.3 Annotated:类型与约束分离(推荐写法)
把约束写在类型里而不是 Field() 里,可复用、更现代:
python
from typing import Annotated
from pydantic import BaseModel, Field
# 定义一次,到处使用
ShortStr = Annotated[str, Field(min_length=1, max_length=50)]
PositiveAmount = Annotated[float, Field(gt=0)]
class Product(BaseModel):
name: ShortStr
category: ShortStr
price: PositiveAmount9.4 自定义类型:Annotated + 校验函数
python
from typing import Annotated
from pydantic import AfterValidator
def must_be_even(v: int) -> int:
if v % 2 != 0:
raise ValueError("必须是偶数")
return v
EvenInt = Annotated[int, AfterValidator(must_be_even)]
class Demo(BaseModel):
num: EvenInt # 传 3 会报错,传 4 通过这是 v2 扩展类型的标准姿势:不写类、不写魔法方法,一个函数搞定。
9.5 Any 与 TypeAdapter
实在不想建模时可以用 data: Any(放弃校验)。另外 Pydantic 提供 TypeAdapter,不建模型也能校验任意类型,特别适合一次性的小校验:
python
from pydantic import TypeAdapter
adapter = TypeAdapter(list[int])
adapter.validate_python(["1", "2", 3]) # → [1, 2, 3]
adapter.validate_json('["a"]') # → 报错9.6 日期与计算属性
python
from pydantic import BaseModel, computed_field
class Rectangle(BaseModel):
width: float
height: float
@computed_field # 像属性一样访问,还会出现在 model_dump() 里
@property
def area(self) -> float:
return self.width * self.height