使用私有字段对模型进行子类化时“不允许使用额外字段”

问题描述 投票:0回答:2

我有两节课:

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
    ,则效果很好,但它位于我正在导入的库中并且无法更改。

我不知道还能尝试什么,有什么建议吗?

python python-3.x pydantic
2个回答
1
投票

默认情况下,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 方法,但它仍然必须声明为私有属性。
    


0
投票
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"

	
© www.soinside.com 2019 - 2024. All rights reserved.