如何让Pydantic V2模型在特定场景下所有字段均为必填
实现Pydantic v2模型的动态严格模式(禁用默认值)
方案1:通过Context参数+根验证器实现动态控制
可以利用model_validate的context传入开关,结合根验证器检查所有字段是否被显式传入——严格模式下,无论字段是否有默认值,都必须在输入中提供。
from pydantic import BaseModel, ValidationError, model_validator from typing import Dict, Any class User(BaseModel): name: str age: int = 18 email: str = "default@example.com" @model_validator(mode="before") def check_strict_mode(cls, data: Dict[str, Any], info) -> Dict[str, Any]: # 从context中读取严格模式开关,默认关闭 strict_mode = info.context.get("strict_mode", False) if strict_mode: all_fields = cls.model_fields.keys() missing_fields = [field for field in all_fields if field not in data] if missing_fields: raise ValueError(f"严格模式下必须传入以下字段: {', '.join(missing_fields)}") return data # 正常模式:可省略带默认值的字段 normal_user = User.model_validate({"name": "Alice"}) print(normal_user) # name='Alice' age=18 email='default@example.com' # 严格模式:缺少字段会触发报错 try: strict_user = User.model_validate({"name": "Bob"}, context={"strict_mode": True}) except ValidationError as e: print(e.errors()) # 提示缺少age和email字段 # 严格模式下传入所有字段则正常通过 strict_user_ok = User.model_validate( {"name": "Bob", "age": 25, "email": "bob@example.com"}, context={"strict_mode": True} ) print(strict_user_ok) # name='Bob' age=25 email='bob@example.com'
方案2:自定义基类封装逻辑(更低样板代码)
如果多个模型都需要严格模式功能,可封装一个基类把验证逻辑统一实现,其他模型直接继承即可:
from pydantic import BaseModel, model_validator from typing import Dict, Any class StrictModeBaseModel(BaseModel): @model_validator(mode="before") def check_strict_mode(cls, data: Dict[str, Any], info) -> Dict[str, Any]: strict_mode = info.context.get("strict_mode", False) if strict_mode: all_fields = cls.model_fields.keys() missing_fields = [f for f in all_fields if f not in data] if missing_fields: raise ValueError(f"严格模式下必须传入字段: {', '.join(missing_fields)}") return data # 继承基类后自动获得严格模式能力 class Product(StrictModeBaseModel): id: str name: str = "Unnamed" price: float = 0.0 # 使用方式一致 try: Product.model_validate({"id": "123"}, context={"strict_mode": True}) except ValueError as e: print(e) # 严格模式下必须传入字段: name, price
注意事项
- 上述方案在验证前置阶段(
mode="before")检查字段完整性,确保默认值不会被自动填充。 - Pydantic v2目前没有内置的全局开关直接禁用所有默认值,上述两种方式是低样板代码的可行实现。
内容的提问来源于stack exchange,提问作者user1894205
相关产品推荐
相关产品推荐

