如何修改BaseDataModel使Pydantic模型实例仅保留显式传入的字段
如何修改BaseDataModel使Pydantic模型实例仅保留显式传入的字段
我明白你的需求:现在创建模型实例时,哪怕没传入的字段也会被自动初始化(带默认值或None),但你希望实例本身只保留那些你显式传入的字段——不管值是不是None,没传的字段就别出现在实例里。
其实Pydantic本身就有内置的机制来跟踪哪些字段是显式传入的,咱们可以利用这个特性来修改BaseDataModel,实现你的需求。
修改后的BaseDataModel代码
from pydantic import BaseModel, root_validator from typing import Dict, Any class BaseDataModel(BaseModel): class Config: populate_by_name = True exclude_unset = True @root_validator(pre=True) def validate_fields(cls, values): # 保留你原来的逻辑:删除模型定义外的字段 for field in values.copy(): if field not in cls.__fields__: del values[field] return values def __init__(self, **data): super().__init__(**data) # 利用Pydantic内置的__fields_set__获取所有显式传入的字段 # 计算出需要移除的字段:所有模型字段 - 显式传入的字段 fields_to_remove = set(self.__fields__) - self.__fields_set__ for field_name in fields_to_remove: delattr(self, field_name) def dict(self, **kwargs): return super().model_dump(exclude_unset=True, **kwargs)
关键修改说明
- 利用Pydantic内置的
__fields_set__:每个Pydantic模型实例都会自动维护这个集合,里面存的是你显式传入的所有字段名——哪怕你传的是None(比如你的branch_id: None),也会被记录在这里。 - 在初始化后移除未传入的字段:在父类初始化完成后,我们找出所有不在
__fields_set__里的模型字段,逐个从实例中删除这些属性。这样实例里就只留下你显式传入的字段了。
效果验证
当你用原来的代码创建实例时:
data = { 'user_id': self.current_user.id, 'medication_history': self.data.medication_history, 'other_disease': self.data.other_disease, 'tobacco_alcohol_use': self.data.tobacco_alcohol_use, 'consumed_medications': self.data.consumed_medications, 'branch_id': None, 'consumed_medications_amount': self.data.consumed_medications_amount, } data = UsersInformationModel(**data)
现在data实例里只会包含你传入的这7个字段,像id、is_vip、creation_tag这些没传的字段,不会出现在实例中——如果你尝试访问data.is_vip,会直接抛出AttributeError,完美符合你的要求。
备注:内容来源于stack exchange,提问作者M a m a D
相关产品推荐
相关产品推荐

