Description
How can I do a partial update of a given resource ? A PATCH is always blocked because of pydantic data validation, as the body doesn't match the schema defined (obviously !).
Is there something I'm missing ? Because I would like to not retrieve the whole object in order to do a simple update on one given field. Either by specifying a partial object or a json patch ?
You can have an additional Pydantic model with all the fields set as optional (with = None).
And then, only update the fields that are passed.
For example, check the project generator and how the update is handled: https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/api/api_v1/endpoints/user.py#L138
And the model has all the fields optional: https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/master/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/models/user.py#L25-L26
Doing it with a PATCH would be the most semantically correct, but FastAPI doesn't really enforce which methods you use or how.
In fact, the project generators tend to use PUT for updates even though they act more like a PATCH (a partial update instead of a full resource replacement). Just because many frontend and other devs aren't very familiar with PATCH.
But the trick in this case is actually in the Pydantic models and what you define as required or not.
That's what I had in mind too, but I thought it was a workaround. I'm going to do things that way then. Thank you !
Cool! Thanks for coming back and closing it.
Hi, with patch request we can omit some fields (not sending it at all, so that field will not be updated), and also send "field": null to set field's value to None. How in this case I can distinguish if field really sent as null, or it was omitted and has default value None set by pydantic model?
@Dock1100 please check the docs: https://fastapi.tiangolo.com/tutorial/body-updates/#partial-updates-with-patch
@tiangolo my bad. exclude_unset=True is what I was looking for, thanks.
Most helpful comment
@tiangolo my bad.
exclude_unset=Trueis what I was looking for, thanks.