我有两节课:
from pydantic import BaseModel, Extra
class Foo(BaseModel):
a: str
class Config:
extra = Extra.forbid
class Bar(Foo):
_secret: str
当我尝试初始化时
Bar
:
Bar(a='a', _secret='b')
我收到以下错误:
pydantic.error_wrappers.ValidationError: 1 validation error for Bar
secret
extra fields not permitted (type=value_error.extra)
如果
Bar
只是 BaseModel
的子类,那么效果很好,但是由于各种其他原因,我需要它从 Foo 子类化
如果
_secret
只是 secret
,那么效果很好,但它确实是我更喜欢作为隐藏属性的东西
如果
Foo
没有 Extra.forbid
,则效果很好,但它位于我正在导入的库中并且无法更改。
我不知道还能尝试什么,有什么建议吗?
默认情况下,Pydantic 基本上完全忽略下划线属性。它们不会作为“字段”添加到模型中。在这种情况下,也可以通过 extra
设置禁止任意非字段属性。如果您现在尝试将
_secret="b"
传递给构造函数,您会收到一条错误消息,因为 _secret
不是字段,并且您尝试传递“额外”值。要解决此问题,您可以重写 __init__
方法并在那里设置
_secret
属性,但请注意使用所有其他关键字参数调用父级 __init__
。此外,您需要将 _secret
声明为 私有属性,方法是为其分配
PrivateAttr()
或配置模型将所有带下划线的(非类)属性解释为私有属性。这有效:
from typing import Any
from pydantic import BaseModel, Extra
class Foo(BaseModel):
a: str
class Config:
extra = Extra.forbid
class Bar(Foo):
_secret: str
def __init__(self, _secret: str, **kwargs: Any) -> None:
self._secret = _secret
super().__init__(**kwargs)
class Config:
underscore_attrs_are_private = True
bar = Bar(a="a", _secret="b")
print(bar) # a='a'
print(bar._secret) # b
我能看到的唯一缺点是,这似乎破坏了 Pydantic PyCharm 插件建议
__init__
参数的一些功能。但在我看来,这并不算太戏剧性。
如果你想避免重写__init__
方法,你必须为
_secret
编写一些 setter 方法,但它仍然必须声明为私有属性。pydantic 2
与
pydantic-settings
和 BaseSettings
一起使用而不是 BaseModel
,则将 extra
的配置值设置为 allow
或 ignore
。这是忽略 pydantic 2
中额外配置的新方法。我收到的错误消息:
不允许额外输入 [type=extra_forbidden, input_value='Collections', input_type=str] 有关更多信息,请访问
https://errors.pydantic.dev/2.7/v/extra_forbidden我对错误的修复:
from pydantic_settings import BaseSettings
class AppSettings(BaseSettings):
ENVIRONMENT: str
PORT: int
ECHO_SQL: bool
DEBUG: bool
class Config:
env_file = ".env"
env_prefix = "APP_"
extra="ignore"