python-3.x 如果在不使用验证器的情况下在字段中传递None,我可以在pydantic中设置默认值吗?

qvtsj1bj  于 2023-07-01  发布在  Python
关注(0)|答案(2)|浏览(152)

如果在不使用验证器的情况下在字段中传递None,我可以在pydantic中设置默认值吗?
我有下面的代码,但在我看来,这里的验证器对于contract_ndfl来说是多余的。有没有什么方法可以不使用验证器?

我的编码:

class User(BaseModel):
        user: int
        s_name: str
        contract_ndfl: Optional[int]
        

       @validator('contract_ndfl')
       def set_contract_ndfl(cls, v):
           return v or 13

心愿码:

class User(BaseModel):
      user: int
      s_name: str
      contract_ndfl: Optional[int] = 13
j91ykkif

j91ykkif1#

也许你可以为所有字段使用一个验证器,并为它定义一个基类!

class NoneDefaultModel(BaseModel):

    @validator("*", pre=True)
    def not_none(cls, v, field):
        if all(
            (
                # Cater for the occasion where field.default in (0, False)
                getattr(field, "default", None) is not None,
                v is None,
            )
        ):
            return field.default
        else:
            return v

然后你可以使用一个子类来实现你的愿望代码:

class Bar(NoneDefaultModel):
    bar: int = 5

Bar(bar=None)
# Bar(bar=5)
mzsu5hc0

mzsu5hc02#

除了使用验证器,您还可以覆盖__init__,以便立即忽略违规字段:

class PreferDefaultsModel(BaseModel):
"""
Pydantic model that will use default values in place of an explicitly passed `None` value.
This is helpful when consuming APIs payloads which may explicitly define a field as `null`
rather than omitting it.
"""

def _field_allows_none(self, field_name):
    """
    Returns True if the field is exists in the model's __fields__ and it's allow_none property is True.
    Returns False otherwise.
    """
    field = self.__fields__.get(field_name)
    if field is None:
        return False
    return field.allow_none

def __init__(self, **data):
    """
    Removes any fields from the data which are None and are not allowed to be None.
    The results are then passed to the super class's init method.
    """
    data_without_null_fields = {k: v for k, v in data.items() if (
            v is not None
            or self._field_allows_none(k)
    )}
    super().__init__(**data_without_null_fields)

然后可以使用它来代替BaseModel,如下所示:

class Foo(PreferDefaultsModel):
    automatic_field = 1
    explicit_field: int = Field(default=2)
    default_factory_field: int = Field(default_factory=lambda:3)
    optional_field: Optional[int] = Field(default=4)
    
f = Foo(automatic_field=None, explicit_field=None, default_factory_field=None, optional_field=None)    
print(f.json(indent=True))
{
 "explicit_field": 2,
 "default_factory_field": 3,
 "optional_field": null,
 "automatic_field": 1
}

请注意,可选字段不会被覆盖。
这种方法只会激活字段的默认行为,而不管它是如何定义的。与使用验证器相比,这不太可能产生意外的结果。

相关问题