Skip to content

24. Body - Updates


1. Body - Updates

  • 이미 저장된 body를 업데이트할 수 있는 몇 가지 방법이 있다.


2. Update replacing with PUT

  • 항목을 업데이트하기 위해 HTTP PUT operation을 사용할 수 있다.


  • 다음의 예제는 jsonable_encoder를 사용하여 입력 데이터를 JSON으로 저장할 수 있는 데이터로 변환하는 예제이다.


from typing import List, Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    price: Optional[float] = 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.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]

@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


  • PUT operation은 기존 데이터를 대체해야 하는 상황에서 사용된다.


1) Warning about replacing

  • 다음과 같이 PUT operation을 사용하여 bar 항목을 업데이트한다고 가정해 보자.


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


  • 위와 같이 업데이트하는 경우, 이미 저장된 속성 "tax": 20.2를 더 이상 포함하지 않기 때문에 입력 모델은 기본값인 "tax": 10.5를 사용하게 된다.
  • 그러므로 업데이트된 새로운 데이터는 "tax": 10.5로 저장된다.


3. Partial updates with PATCH

  • 항목의 일부분만 업데이트하기 위해 HTTP PATCH operation을 사용할 수 있다.
  • 즉, 항목의 나머지는 그대로 두고 업데이트하려는 데이터만 보낼 수 있다.


Note

  • 하지만 일반적으로 PATCH보다 PUT을 더 많이 사용한다.


1) Using Pydantic's exclude_unset parameter

  • 부분적으로 업데이트를 하고 싶다면 item.dict(exclude_unset=True)와 같이 Pydantic 모델의 .dict()에서 exclude_unset 매개변수를 사용하는 것이 유용하다.
  • 이렇게 하면, 기본값을 제외하고 항목 모델을 생성할 때 새로 설정한 데이터만 포함하는 dict가 생성된다.


  • 다음의 예제는 기본값을 생략하고 새로 설정된 데이터만 포함하는 dict를 생성하는 예제이다.


from typing import List, Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    price: Optional[float] = 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.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]

@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


2) Using Pydantic's update parameter

  • stored_item_model.copy(update=update_data)와 같이 .copy()를 사용하여 기존 모델의 복사본을 만들고 업데이트할 데이터가 포함된 dict와 함께 update 매개변수를 전달할 수 있다.


from typing import List, Optional
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    price: Optional[float] = 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.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]

@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

References