I want to allow users to selectively update fields using PUT calls. On the pydantic model, I have made the fields Optional. In the FastAPI handler if the model attribute is None, then the field was not given and I do not update it.
The problem with this approach is that there is no way for the client to "blank out" a field that isn't required for certain types.
In particular, I have date fields that I want clients to be able to clear by sending in a null in the JSON. How can I detect the difference between the client sending null or the client not sending the field/value at all? The model attribute is just None in either case.
Pydantic models can be defined with a custom root type by declaring the __root__ field. The root type can be any type supported by pydantic, and is specified by the type hint on the __root__ field.
constr is a specific type that give validation rules regarding this specific type. You have equivalent for all classic python types.
Pydantic is a useful library for data parsing and validation. It coerces input types to the declared type (using type hints), accumulates all the errors using ValidationError & it's also well documented making it easily discoverable.
The type Optional [x] is a shorthand for Union [x, None]. Optional [x] can also be used to specify a required field that can take None as a value. See more details in Required Fields. pydantic uses python's standard enum classes to define choices. Pydantic supports the following datetime types: datetime fields can be:
Callable fields only perform a simple check that the argument is callable; no validation of arguments, their types, or the return type is performed. pydantic supports the use of Type [T] to specify that a field may only accept classes (not instances) that are subclasses of T.
Newer versions of pydantic (starting with 0.20) handle your use case much better. If you want to be able to dynamically modify a field according to another one, you can use the values argument. It holds all the previous fields, and careful: the order matters. You could do this either using a validator or a root_validator.
In most of the cases you will probably be fine with standard pydantic models. You can use Generic Classes as field types and perform custom validation based on the "type parameters" (or sub-types) with __get_validators__.
The pydantic documentation desccribes two options that can be used with the .dict()
method of models.
exclude_unset
: whether fields which were not explicitly set when creating the model should be excluded from the returned dictionary; default False. Prior to v1.0, exclude_unset was known as skip_defaults; use of skip_defaults is now deprecated
exclude_defaults
: whether fields which are equal to their default values (whether set or otherwise) should be excluded from the returned dictionary; default False
So you can create a model class with optional fields:
from typing import Optional
from pydantic import BaseModel
class MyModel(BaseModel):
foo: Optional[int] = None
bar: Optional[int] = None
And still generate a dict with fields explicitely set to None, but without default values:
baz = MyModel(foo=None)
assert baz.dict(exclude_unset=True) == {"foo": None}
baz = MyModel(bar=None)
assert baz.dict(exclude_unset=True) == {"bar": None}
You can check obj.__fields_set__
to see whether the value was missing or not.
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"}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With