Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Join theFastAPI Cloud waiting list 🚀
Follow@fastapi onX (Twitter) to stay updated
FollowFastAPI onLinkedIn to stay updated
Subscribe to theFastAPI and friends newsletter 🎉
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor

Body - Updates

Update replacing withPUT

To update an item you can use theHTTPPUT operation.

You can use thejsonable_encoder to convert the input data to data that can be stored as JSON (e.g. with a NoSQL database). For example, convertingdatetime tostr.

fromfastapiimportFastAPIfromfastapi.encodersimportjsonable_encoderfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:str|None=Nonedescription:str|None=Noneprice:float|None=Nonetax:float=10.5tags:list[str]=[]items={"foo":{"name":"Foo","price":50.2},"bar":{"name":"Bar","description":"The bartenders","price":62,"tax":20.2},"baz":{"name":"Baz","description":None,"price":50.2,"tax":10.5,"tags":[]},}@app.get("/items/{item_id}",response_model=Item)asyncdefread_item(item_id:str):returnitems[item_id]@app.put("/items/{item_id}",response_model=Item)asyncdefupdate_item(item_id:str,item:Item):update_item_encoded=jsonable_encoder(item)items[item_id]=update_item_encodedreturnupdate_item_encoded

PUT is used to receive data that should replace the existing data.

Warning about replacing

That means that if you want to update the itembar usingPUT with a body containing:

{"name":"Barz","price":3,"description":None,}

because it doesn't include the already stored attribute"tax": 20.2, the input model would take the default value of"tax": 10.5.

And the data would be saved with that "new"tax of10.5.

Partial updates withPATCH

You can also use theHTTPPATCH operation topartially update data.

This means that you can send only the data that you want to update, leaving the rest intact.

Note

PATCH is less commonly used and known thanPUT.

And many teams use onlyPUT, even for partial updates.

You arefree to use them however you want,FastAPI doesn't impose any restrictions.

But this guide shows you, more or less, how they are intended to be used.

Using Pydantic'sexclude_unset parameter

If you want to receive partial updates, it's very useful to use the parameterexclude_unset in Pydantic's model's.model_dump().

Likeitem.model_dump(exclude_unset=True).

That would generate adict with only the data that was set when creating theitem model, excluding default values.

Then you can use this to generate adict with only the data that was set (sent in the request), omitting default values:

fromfastapiimportFastAPIfromfastapi.encodersimportjsonable_encoderfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:str|None=Nonedescription:str|None=Noneprice:float|None=Nonetax:float=10.5tags:list[str]=[]items={"foo":{"name":"Foo","price":50.2},"bar":{"name":"Bar","description":"The bartenders","price":62,"tax":20.2},"baz":{"name":"Baz","description":None,"price":50.2,"tax":10.5,"tags":[]},}@app.get("/items/{item_id}",response_model=Item)asyncdefread_item(item_id:str):returnitems[item_id]@app.patch("/items/{item_id}")asyncdefupdate_item(item_id:str,item:Item)->Item:stored_item_data=items[item_id]stored_item_model=Item(**stored_item_data)update_data=item.model_dump(exclude_unset=True)updated_item=stored_item_model.model_copy(update=update_data)items[item_id]=jsonable_encoder(updated_item)returnupdated_item

Using Pydantic'supdate parameter

Now, you can create a copy of the existing model using.model_copy(), and pass theupdate parameter with adict containing the data to update.

Likestored_item_model.model_copy(update=update_data):

fromfastapiimportFastAPIfromfastapi.encodersimportjsonable_encoderfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:str|None=Nonedescription:str|None=Noneprice:float|None=Nonetax:float=10.5tags:list[str]=[]items={"foo":{"name":"Foo","price":50.2},"bar":{"name":"Bar","description":"The bartenders","price":62,"tax":20.2},"baz":{"name":"Baz","description":None,"price":50.2,"tax":10.5,"tags":[]},}@app.get("/items/{item_id}",response_model=Item)asyncdefread_item(item_id:str):returnitems[item_id]@app.patch("/items/{item_id}")asyncdefupdate_item(item_id:str,item:Item)->Item:stored_item_data=items[item_id]stored_item_model=Item(**stored_item_data)update_data=item.model_dump(exclude_unset=True)updated_item=stored_item_model.model_copy(update=update_data)items[item_id]=jsonable_encoder(updated_item)returnupdated_item

Partial updates recap

In summary, to apply partial updates you would:

  • (Optionally) usePATCH instead ofPUT.
  • Retrieve the stored data.
  • Put that data in a Pydantic model.
  • Generate adict without default values from the input model (usingexclude_unset).
    • This way you can update only the values actually set by the user, instead of overriding values already stored with default values in your model.
  • Create a copy of the stored model, updating its attributes with the received partial updates (using theupdate parameter).
  • Convert the copied model to something that can be stored in your DB (for example, using thejsonable_encoder).
    • This is comparable to using the model's.model_dump() method again, but it makes sure (and converts) the values to data types that can be converted to JSON, for example,datetime tostr.
  • Save the data to your DB.
  • Return the updated model.
fromfastapiimportFastAPIfromfastapi.encodersimportjsonable_encoderfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:str|None=Nonedescription:str|None=Noneprice:float|None=Nonetax:float=10.5tags:list[str]=[]items={"foo":{"name":"Foo","price":50.2},"bar":{"name":"Bar","description":"The bartenders","price":62,"tax":20.2},"baz":{"name":"Baz","description":None,"price":50.2,"tax":10.5,"tags":[]},}@app.get("/items/{item_id}",response_model=Item)asyncdefread_item(item_id:str):returnitems[item_id]@app.patch("/items/{item_id}")asyncdefupdate_item(item_id:str,item:Item)->Item:stored_item_data=items[item_id]stored_item_model=Item(**stored_item_data)update_data=item.model_dump(exclude_unset=True)updated_item=stored_item_model.model_copy(update=update_data)items[item_id]=jsonable_encoder(updated_item)returnupdated_item

Tip

You can actually use this same technique with an HTTPPUT operation.

But the example here usesPATCH because it was created for these use cases.

Note

Notice that the input model is still validated.

So, if you want to receive partial updates that can omit all the attributes, you need to have a model with all the attributes marked as optional (with default values orNone).

To distinguish from the models with all optional values forupdates and models with required values forcreation, you can use the ideas described inExtra Models.


[8]ページ先頭

©2009-2026 Movatter.jp