fastapi之如何处理更新数据的请求

393 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

请求方式PUT

  • 对于restful接口设计,想获取数据使用GET,想创建数据使用POST,想更新数据使用PUT和PATCH
  • 比如下面的例子中:我们想更新key为bar的数据,新数据放在请求体中,通过PUT请求实现。
 from typing import List, Union
 ​
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class Item(BaseModel):
     name: Union[str, None] = None
     description: Union[str, None] = None
     price: Union[float, None] = None
     tax: float = 10.5
     tags: 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.put("/items/{item_id}", response_model=Item)
 async def update_item(item_id: str, item: Item):
     update_item_encoded = jsonable_encoder(item)
     items[item_id] = update_item_encoded
     return update_item_encoded
  • 路径参数item_id为bar,请求体数据为:
 {
     "name": "Barz",
     "price": 3,
     "description": None,
 }
  • 具体更新逻辑分析如下:

    • 通过路径参数item_id,在items这个字典中找到bar对应的值
    • 请求体变量item是新的数据,使用jsonable_encoder这个工具转化为可以序列化的字典。
    • 然后使用items[item_id] = update_item_encoded来实现更新逻辑。
    • 最后返回更新后的数据。
  • 因此,PUT一般用来接收数据并替换已经存在的数据
  • 上面我们使用PUT的例子有个小点:新的数据中没有tax这个字段,所有更新后tax就变成默认值10.5了
  • 如果想局部更新某些字段的值,一般我们会使用PATCH

局部更新PATCH

  • 一般想要局部更细某些数据,使用的请求方式是PATCH
  • 对于上例,我们如果不想要更新tax这个值,做法可以使用exclude_unset
 from typing import List, Union
 ​
 from fastapi import FastAPI
 from fastapi.encoders import jsonable_encoder
 from pydantic import BaseModel
 ​
 app = FastAPI()
 ​
 ​
 class Item(BaseModel):
     name: Union[str, None] = None
     description: Union[str, None] = None
     price: Union[float, None] = None
     tax: float = 10.5
     tags: 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.patch("/items/{item_id}", response_model=Item)
 async def update_item(item_id: str, item: Item):
     stored_item_data = items[item_id]
     stored_item_model = Item(**stored_item_data)
     update_data = item.dict(exclude_unset=True)
     updated_item = stored_item_model.copy(update=update_data)
     items[item_id] = jsonable_encoder(updated_item)
     return updated_item
  • item.dict(exclude_unset=True)会将请求体中来的数据转化为字典的同时,把没有设置值的字段过滤掉。
  • 所有得到的值update_data就没有了tax这个字段,
  • 然后在使用stored_item_model.copy(update=update_data),把stored_item_model中通过update指定的三个字段值更新
  • 最后使用jsonable_encoder将数据专为可序列化的字段。