Pydantic中FieldInfo内的ForwardRef未被update_forward_refs更新导致construct()实例化报错的解决方法咨询
Pydantic中FieldInfo内的ForwardRef未被update_forward_refs更新导致construct()实例化报错的解决方法咨询
这个问题我之前踩过一模一样的坑!确实,update_forward_refs()只会处理字段的类型注解(也就是A.__fields__['b'].type_这部分),但不会自动更新Field参数里的default_factory这类自定义属性——这是Pydantic V1版本的一个小局限。
快速临时解决:手动更新default_factory
在调用update_forward_refs()之后,直接把field_info里的default_factory替换成实际的B类就行,代码示例如下:
from typing import ForwardRef from pydantic import BaseModel, Field ClassB = ForwardRef('B', is_class=True) class A(BaseModel): b: ClassB = Field(default_factory=ClassB) class Config: arbitrary_types_allowed = True class B: pass # 先更新字段的类型引用 A.update_forward_refs() # 手动替换default_factory为实际的B类 A.__fields__['b'].field_info.default_factory = B # 现在可以正常调用construct()了 instance = A.construct() print(instance.b) # 输出 <__main__.B object at 0x...>
更优雅的写法:调整类定义顺序
如果可以调整代码结构,完全可以等B类定义完成后再给A添加字段,这样就不用依赖ForwardRef了:
from pydantic import BaseModel, Field class A(BaseModel): class Config: arbitrary_types_allowed = True class B: pass # 等B定义好后,动态添加字段 A.__fields__['b'] = Field(default_factory=B, annotation=B) # 直接调用construct即可 A.construct()
长期推荐方案:升级到Pydantic V2
如果你的项目可以升级到Pydantic V2,这个问题会被自动解决。V2里的model_rebuild()方法会更全面地处理所有引用,包括default_factory里的ForwardRef:
from typing import ForwardRef from pydantic import BaseModel, Field ClassB = ForwardRef('B') class A(BaseModel): b: ClassB = Field(default_factory=ClassB) class Config: arbitrary_types_allowed = True class B: pass # V2用model_rebuild代替update_forward_refs A.model_rebuild() # V2里对应的构造方法是model_construct instance = A.model_construct()
问题根源解释
本质上,update_forward_refs()的设计目标只是解析字段的类型注解(也就是你定义的b: ClassB这部分),而Field(default_factory=ClassB)里的default_factory是作为参数传入的,Pydantic不会自动追踪并更新这个参数里的ForwardRef对象,所以需要我们手动处理。
备注:内容来源于stack exchange,提问作者Jimothy
相关产品推荐
相关产品推荐

