根据文档,需要Pydantic“ORM 模式”(通过orm_mode = Truein启用)来启用该方法,以便通过从另一个类实例读取属性来创建模型实例。如果未启用 ORM 模式,该方法将引发异常。Configfrom_ormfrom_orm
我的疑问是:
幸运的是,至少第一个问题可以相当容易地回答。
截至 version 1.10.4,只有两个地方(除了插件)orm_mode可以发挥作用。
BaseModel.from_orm这基本上是一个替代构造函数。它放弃了常规__init__方法,转而采用略有不同的设置。不知道为什么要这样设计。但orm_mode必须设置该标志才能使该方法不引发错误。直截了当。我在这里看不到隐藏的惊喜。
BaseModel.validate此方法是该类型的默认验证器BaseModel。如果没有该orm_mode标志,验证器期望的值是 1) 该特定模型的实例,2) 可以解压到该模型的构造函数中的字典,或者 3) 可以强制转换为字典的值,然后被解包到该模型的构造函数中。
如果orm_mode是True并且验证器遇到的东西既不是模型的实例也不是字典,它假设它是一个可以传递给上述方法的对象from_orm并调用它而不是尝试dict强制。
请注意,在初始化期间不会调用此方法,并且如果将某些内容分配给任何类型的模型字段,则不会调用BaseModel该方法。仅当您处理嵌套模型(并且用作数据输入的对象也是嵌套的)时,即处理具有用另一个模型注释的字段的模型时,它才发挥作用。只有这样外层模型才会调用validate内层模型的方法。
考虑以下:
from __future__ import annotations
from typing import TypeVar
from pydantic import BaseModel
M = TypeVar("M", bound=BaseModel)
class Foo(BaseModel):
x: int
@classmethod
def validate(cls: type[M], value: object) -> M:
print("called `Foo.validate`")
return super().validate(value)
class Config:
orm_mode = True
class A:
x = 1
foo = Foo.from_orm(A)
print(foo.json())
Run Code Online (Sandbox Code Playgroud)
输出是{"x": 1},我们看到它Foo.validate没有被调用。
现在我们稍微扩展一下:
...
class Bar(BaseModel):
f: Foo
class Config:
orm_mode = True
class B:
f = A
bar = Bar.from_orm(B)
print(bar.json())
Run Code Online (Sandbox Code Playgroud)
新的输出:
called `Foo.validate`
{"f": {"x": 1}}
Run Code Online (Sandbox Code Playgroud)
现在验证器已按预期被调用,如果我们要注入类似的print语句,Foo.from_orm当我们在被调用Bar.from_orm后立即调用时,我们会看到它也被调用Foo.validate。
这可能与某些利基情况相关,但一般来说,我认为from_orm验证过程中的这种级联应用程序是有意义的,并且应该适应主要的预期用例——数据库 ORM 对象。
如果您希望在验证期间有不同的行为,您始终可以定义自己的验证器方法,甚至简单地覆盖该validate方法(取决于您的用例)。
源代码中没有其他用途orm_mode,所以就功能而言就是这样。
在我看来,性能在这些上下文中并不真正相关,因为它只是初始化模型实例的一种完全不同的方式。除非您想知道首先手动将 ORM 对象转换为字典并将其传递给它parse_obj或仅调用from_orm它是否更快。不过,您可以相当容易地进行基准测试。
BaseModel据我所知,该配置设置不会影响其他功能(性能方面)。
对于你的第二个问题,我只能推测。所以我不会回答。有一个问题已经开放了一段时间,建议完全删除该设置,这似乎符合您的推理,即在任何情况下都不应该“选择加入”。我不确定 Samuel Colvin 是否仍然接受 v2 的向后不兼容功能请求,但这个问题并没有引起太多关注。您可能想参加那里。
| 归档时间: |
|
| 查看次数: |
15268 次 |
| 最近记录: |