幸运的是,至少第一个问题可以相当容易地回答。
从版本 1.10.4 开始,有只有两个地方(除了插件),orm_mode 发挥作用。
这基本上是一个替代构造函数。它放弃了常规的 __init__ 方法,转而采用略有不同的设置。不确定,为什么这样设计。但是必须为该方法设置 orm_mode 标志才能不引发错误。直截了当。我在这里看不到隐藏的惊喜。
此方法是 BaseModel 类型的默认验证器。如果没有 orm_mode 标志,验证器期望的值是 1) 该特定模型的实例,2) 可以解压到该模型的构造函数中的字典,或 3) 可以是的东西被胁迫到字典,然后解压到该模型的构造函数中。
如果 orm_mode 是 True 并且验证器遇到的是不是模型的一个实例和不是一个字典,它假设它是一个可以传递给上述from_orm方法和calls that的对象,而不是尝试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())
输出是{"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())
新的输出:
called `Foo.validate`
{"f": {"x": 1}}
现在验证器按预期被调用,如果我们将类似的print语句注入Foo.from_orm,当我们在调用Foo.validate后立即调用Bar.from_orm时,我们会看到它也被调用了。
这在某些特定情况下可能是相关的,但一般来说,我认为在验证期间 from_orm 的这种级联应用是有意义的,并且应该适应主要的预期用例——数据库 ORM 对象。
如果您希望在验证期间有不同的行为,您始终可以定义自己的 validator 方法,甚至可以简单地覆盖 validate 方法(取决于您的用例)。
orm_mode在源代码中没有其他用途,所以就功能而言就是这样。
在 IMO 的那些上下文中,性能并不真正相关,因为它只是初始化模型实例的一种完全不同的方式。除非您对首先手动将您的 ORM 对象转换为字典并将其传递给 parse_obj 或仅调用 from_orm 是否更快感兴趣。不过,您可以很容易地对其进行基准测试。
BaseModel 的其他功能不会以我所见的任何方式受到该配置设置的影响(性能方面)。
对于你的第二个问题,我只能推测。所以我会避免回答。有一个 issue 已经开放了一段时间,建议完全删除该设置,这似乎符合您的推理,即在任何情况下都不应该“选择加入”。我不确定 Samuel Colvin 是否仍在接受 v2 的向后不兼容功能请求,但这个问题并没有引起太多关注。你可能想在那里参加。