Pydantic:检测字段值是否丢失或为 null
Pydantic: Detect if a field value is missing or given as null
我想允许用户使用 PUT 调用有选择地更新字段。在 pydantic 模型上,我将字段设置为可选。在 FastAPI 处理程序中,如果模型属性为 None,则未提供该字段,我不会更新它。
这种方法的问题是客户端无法“删除”某些类型不需要的字段。
特别是,我希望客户能够通过在 JSON 中发送空值来清除日期字段。如何检测客户端发送 null 或客户端根本不发送 field/value 之间的区别?在任何一种情况下,模型属性都只是 None。
pydantic documentation 描述了两个可以与模型的 .dict()
方法一起使用的选项。
exclude_unset
:是否应该从返回的字典中排除在创建模型时未明确设置的字段;默认为假。在 v1.0 之前,exclude_unset 被称为 skip_defaults; skip_defaults 现已弃用
exclude_defaults
:是否应从返回的字典中排除等于其默认值(无论是否设置)的字段;默认假
因此您可以创建一个模型 class,其中包含可选字段:
from typing import Optional
from pydantic import BaseModel
class MyModel(BaseModel):
foo: Optional[int] = None
bar: Optional[int] = None
并且仍然生成一个字段明确设置为 None 但没有默认值的字典:
baz = MyModel(foo=None)
assert baz.dict(exclude_unset=True) == {"foo": None}
baz = MyModel(bar=None)
assert baz.dict(exclude_unset=True) == {"bar": None}
您可以检查 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"}
我想允许用户使用 PUT 调用有选择地更新字段。在 pydantic 模型上,我将字段设置为可选。在 FastAPI 处理程序中,如果模型属性为 None,则未提供该字段,我不会更新它。
这种方法的问题是客户端无法“删除”某些类型不需要的字段。
特别是,我希望客户能够通过在 JSON 中发送空值来清除日期字段。如何检测客户端发送 null 或客户端根本不发送 field/value 之间的区别?在任何一种情况下,模型属性都只是 None。
pydantic documentation 描述了两个可以与模型的 .dict()
方法一起使用的选项。
exclude_unset
:是否应该从返回的字典中排除在创建模型时未明确设置的字段;默认为假。在 v1.0 之前,exclude_unset 被称为 skip_defaults; skip_defaults 现已弃用exclude_defaults
:是否应从返回的字典中排除等于其默认值(无论是否设置)的字段;默认假
因此您可以创建一个模型 class,其中包含可选字段:
from typing import Optional
from pydantic import BaseModel
class MyModel(BaseModel):
foo: Optional[int] = None
bar: Optional[int] = None
并且仍然生成一个字段明确设置为 None 但没有默认值的字典:
baz = MyModel(foo=None)
assert baz.dict(exclude_unset=True) == {"foo": None}
baz = MyModel(bar=None)
assert baz.dict(exclude_unset=True) == {"bar": None}
您可以检查 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"}