如何用Pydantic BaseModel管理场景可选输入参数?
如何用Pydantic BaseModel实现参数依赖校验规则?
我用pydantic.BaseModel定义了一个输入类Product,其中部分参数存在场景化的必填规则:
from pydantic import BaseModel class Product(BaseModel): name: str sale_price: float | None = None cost_manufacture: float | None = None cost_transport: float | None = None earning_ratio: float | None = None
规则如下:
- 若提供
sale_price,则cost_manufacture、cost_transport和earning_ratio必须保持默认值None,无需提供 - 若未提供
sale_price,则必须同时提供cost_manufacture、cost_transport和earning_ratio
之前仅通过Field添加描述的方式不够优雅,会增加用户阅读成本,需要一种能自动校验该依赖规则的实现方式。
解决方案:使用Pydantic的模型验证器
针对Pydantic v2版本
使用model_validator(设置mode='after')实现跨字段的依赖校验:
from pydantic import BaseModel, model_validator, ValidationError class Product(BaseModel): name: str sale_price: float | None = None cost_manufacture: float | None = None cost_transport: float | None = None earning_ratio: float | None = None @model_validator(mode='after') def check_parameter_dependency(self) -> 'Product': # 提供sale_price时,检查成本相关参数是否全为None if self.sale_price is not None: if any([self.cost_manufacture, self.cost_transport, self.earning_ratio]): raise ValueError("当提供sale_price时,cost_manufacture、cost_transport和earning_ratio必须为None") # 未提供sale_price时,检查成本相关参数是否全部提供 else: if not all([self.cost_manufacture, self.cost_transport, self.earning_ratio]): raise ValueError("当未提供sale_price时,必须同时提供cost_manufacture、cost_transport和earning_ratio") return self # 测试示例 if __name__ == "__main__": # 合法:仅提供sale_price try: product1 = Product(name="Test", sale_price=100.0) print(product1) except ValidationError as e: print(e) # 合法:仅提供成本相关参数 try: product2 = Product(name="Test", cost_manufacture=50.0, cost_transport=10.0, earning_ratio=0.2) print(product2) except ValidationError as e: print(e) # 非法:同时提供sale_price和成本参数 try: product3 = Product(name="Test", sale_price=100.0, cost_manufacture=50.0) print(product3) except ValidationError as e: print(e) # 非法:未提供sale_price但缺少成本参数 try: product4 = Product(name="Test", cost_manufacture=50.0, cost_transport=10.0) print(product4) except ValidationError as e: print(e)
针对Pydantic v1版本
若仍使用Pydantic v1,可使用root_validator(设置pre=False):
from pydantic import BaseModel, root_validator, ValidationError class Product(BaseModel): name: str sale_price: float | None = None cost_manufacture: float | None = None cost_transport: float | None = None earning_ratio: float | None = None @root_validator(pre=False) def check_parameter_dependency(cls, values): sale_price = values.get("sale_price") cost_manufacture = values.get("cost_manufacture") cost_transport = values.get("cost_transport") earning_ratio = values.get("earning_ratio") if sale_price is not None: if any([cost_manufacture, cost_transport, earning_ratio]): raise ValueError("当提供sale_price时,cost_manufacture、cost_transport和earning_ratio必须为None") else: if not all([cost_manufacture, cost_transport, earning_ratio]): raise ValueError("当未提供sale_price时,必须同时提供cost_manufacture、cost_transport和earning_ratio") return values # 测试示例同v2版本
优势说明
- 自动执行校验,不符合规则时直接抛出
ValidationError,无需用户手动判断 - 校验逻辑集中,代码结构清晰,维护成本低
- 完全兼容Pydantic原生校验机制,适配现有输入处理流程
内容的提问来源于stack exchange,提问作者aura
相关产品推荐
相关产品推荐

