Pydantic:检测字段值是否缺失或为空

Jer*_*emy 4 python pydantic

我希望允许用户使用 PUT 调用有选择地更新字段。在 pydantic 模型上,我将字段设为可选。在 FastAPI 处理程序中,如果模型属性为 None,则未给出该字段并且我不更新它。

这种方法的问题在于客户端无法“清除”某些类型不需要的字段。

特别是,我希望客户端能够通过在 JSON 中发送空值来清除日期字段。如何检测客户端发送 null 或客户端根本不发送字段/值之间的差异?在任何一种情况下,模型属性都只是 None 。

ale*_*ame 21

使用 Pydantic v1,您可以检查obj.__fields_set__该值是否丢失。

from typing import Optional
from pydantic import BaseModel

class Foo(BaseModel):
    first: Optional[int] = None
    second: Optional[int] = None

foo = Foo.parse_raw('{"first": null}')

assert foo.first is None and foo.second is None
assert foo.__fields_set__ == {"first"}
Run Code Online (Sandbox Code Playgroud)


Mar*_*aff 7

区分提供值None和无值的另一种方法是使用@root_validator(pre=True); 例如,允许可为空的非可选字段。

老实说,我不确定它是否适合您的用例,但各种谷歌搜索都指向我这里,因为它回答了您的问题标题,所以无论如何我都会发布我的答案。

优点是它是在“模型内部”检查的,并且可以通过例如MyModel.validate(my_dict)无需外部额外断言的方式进行验证。

from typing import Optional, root_validator
from pydantic import BaseModel


class MyModel(BaseModel):
    foo: Optional[int]
    bar: Optional[int]

    @root_validator(pre=True)
    def _check_whether_foo_present(cls, values):
        if not "foo" in values:
            # do something, e.g.:
            raise ValueError('"foo" was not provided to the model')
        return values
Run Code Online (Sandbox Code Playgroud)


gch*_*bon 5

pydantic文档desccribes可与使用两个选项.dict()的模型方法。

  • exclude_unset: 创建模型时未明确设置的字段是否应从返回的字典中排除;默认为假。在 v1.0 之前, exclude_unset 被称为 skip_defaults;现在不推荐使用skip_defaults

  • exclude_defaults:是否应从返回的字典中排除等于其默认值(无论是否设置)的字段;默认错误

所以你可以创建一个带有可选字段的模型类:

from typing import Optional
from pydantic import BaseModel


class MyModel(BaseModel):
    foo: Optional[int] = None
    bar: Optional[int] = None
Run Code Online (Sandbox Code Playgroud)

并且仍然生成一个字段明确设置为无的字典,但没有默认值:

baz = MyModel(foo=None)
assert baz.dict(exclude_unset=True) == {"foo": None}

baz = MyModel(bar=None)
assert baz.dict(exclude_unset=True) == {"bar": None}

Run Code Online (Sandbox Code Playgroud)