【问题标题】:Pydantic private argument for recursive model instantiation递归模型实例化的 Pydantic 私有参数
【发布时间】:2021-11-05 04:58:10
【问题描述】:

我有一个 Pydantic 模型,它基本上是其他模型的列表,如下所示:


class Thing(BaseModel):
    _api: Api = PrivateAttr()
    id: int
    name: str

class ThingList(BaseModel):
    _api: API = PrivateAttr()
    __root__ = List[Thing]

这些东西是从我对外部 API 进行的 API 调用的 JSON 内容中解析出来的,例如:

def some_method_somewhere(self, api, **other_args)
    ...
    response = await api.send('GET', url)
    return ThingList(__root__=response, api=api)

但是,我不知道如何让 Thing 模型的 Pydantic 实例化接收 api 参数。

我能看到的唯一简单方法是让某个函数返回一个我可以从 PrivateAttr(default_factory=func) 调用的全局值,但那有异味。

此功能应尽可能通用。目前 ThingList 可以通过迭代 Response 对象替换为普通列表(随意假装它来自请求),但将来不能保证这是真的。 (事实上​​,其他属性很可能来自需要集成到 ThingList 中的 API。

我梦想的解决方案是在 ThingList 类的某个地方扩展一个方法,但我找不到 Pydantic 是如何做到的。

【问题讨论】:

    标签: python pydantic


    【解决方案1】:

    您可以在封闭模型的__init__ 方法中更新嵌套对象的私有属性:

    class Thing(BaseModel):
        _api: str = PrivateAttr()
        id: int
        name: str
    
    
    class ThingList(BaseModel):
        _api: str = PrivateAttr()
        __root__: List[Thing]
    
        def __init__(self, *, api, **data):
            super().__init__(**data)
            self._api = api
            for item in self.__root__:
                item._api = api
    

    【讨论】:

    • 这很有希望。但是,它会给我带来验证器的麻烦吗,因为它在初始化时不存在?
    • 也许,在验证器的情况下,很高兴看到您的用例的最小示例。
    • 我在考虑 pydantic 默认验证器。但是我已经根据您的建议运行了代码,并且他们不会抱怨实例化后的分配。所以没关系。
    猜你喜欢
    • 2020-07-04
    • 2021-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2020-01-06
    • 1970-01-01
    • 2014-11-01
    相关资源
    最近更新 更多