Programming Language/Python

[FastAPI] 4. Request Body

LeeJaeJun 2024. 6. 19. 00:32
728x90
반응형

Reqeust Body

  • 클라이언트가 API에 데이터를 전송할 때 사용
  • 즉, 클라이언트가 API로 보내는 데이터가 Request Body(Response Body는 API가 클라이언트로 보내는 데이터)
  • API는 거의 항상 Response Body을 보내야 하지만, 클라이언트는 항상 Request Body을 보낼 필요는 없음
  • Request Body를 선언하기 위해 FastAPI에서는 Pydantic model을 상속받아 사용
    • Pydantic: API에서 입력받는 데이터의 구조와 유형을 정의하는 데 사용. 데이터의 유효성을 자동 검증하고, 올바른 유형 변환
    • 데이터의 무결성을 보장, API의 신뢰성과 사용성 증가!
from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    return item
  • 데이터 모델을 생성하기 위해 BaseModel을 상속받는 클래스를 정의(여기서는 Item class)
  • API가 받을 데이터의 구조를 정의하는 class
class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

 

  • name: string 타입의 required 필드
  • description: string 타입의 optional 필드, 기본값은 None
  • price: float 타입의 required 필드
  • tax: float 타입의 optional 필드, 기본값은 None
# 다음과 같은 JSON object(or python dictionary)로 request body가 구성되어야 함
{
    "name": "Foo",
    "description": "An optional description",
    "price": 45.2,
    "tax": 3.5
}

# optional인 변수들은 제외 가능(default 값 사용)
{
    "name": "Foo",
    "price": 45.2
}
  • 생성한 클래스를 parameter type으로 설정하여, 클라이언트가 보낸 JSON 데이터를 Pydantic으로 생성한 모델(여기서는 Item)로 검증하고 변환
  • async def create_item(item: Item)
from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None


app = FastAPI()


@app.post("/items/")
async def create_item(item: Item):
    item_dict = item.dict()
    if item.tax:
        price_with_tax = item.price + item.tax
        item_dict.update({"price_with_tax": price_with_tax})
    return item_dict
  • model object의 속성들에 대해 직접 접근해서 사용 가능
    • item.price + item.tax (item이라는 model object)

 

동작 과정 (자동 수행)

  1. 요청 본문을 JSON으로 읽음
  2. 해당 데이터를 정의된 타입으로 변환
  3. 데이터를 검증
  4. 데이터가 유효하지 않은 경우, 명확한 오류 메시지를 반환
  5. 검증된 데이터를 item 매개변수로 함수에 전달.
  6. 함수 내에서 Item 타입으로 선언된 item을 사용하면 편집기에서 자동 완성 및 타입 힌트를 제공
  7. 생성된 모델에 대한 JSON Schema 정의를 자동으로 생성하고, OpenAPI 스키마의 일부로 포함시킴 이는 자동 문서화 UI에서 사용

JSON Schema 정의를 자동으로 생성하고, OpenAPI 스키마의 일부로 포함시킴

 

매개변수 인식 방법

from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

app = FastAPI()

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
    result = {"item_id": item_id, **item.dict()}
    if q:
        result.update({"q": q})
    return result

 

  • Path parameter:
    • URL 경로에 명시된 매개변수 ({item_id})는 path parameter로 인식
    • URL 경로에서 데이터를 가져옴
  • Query Parameter:
    • 기본 데이터 타입 (int, float, str, bool 등)으로 선언된 매개변수는 Query parameter로 인식
    • URL의 쿼리 문자열에서 데이터를 가져옴
  • Request Body:
    • Pydantic 모델로 선언된 매개변수는 request body에서 가져옴
  • FastAPI는 각 매개변수를 올바른 위치에서 자동으로 인식하고 처리

 

** 연산자

  • Python에서 dictionary의 항목들을 unpacking하는 데 사용
  • 이를 통해 사전의 키-값 쌍을 개별적인 키워드 인수로 분해 가능
def my_function(a, b, c):
    print(a, b, c)

data = {'a': 1, 'b': 2, 'c': 3}

my_function(**data)
  • my_function(**data) my_function(a=1, b=2, c=3)와 동일하게 동작
from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

app = FastAPI()

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_id": item_id, **item.dict()}

 

  • item.dict() 호출
    • item.dict()는 item의 데이터를 dictionary 형태로 변환. 예를 들어, Item(name="example", description="example item", price=10.0, tax=0.5)라면 item.dict()는 {"name": "example", "description": "example item", "price": 10.0, "tax": 0.5}를 반환합니다.
  • **item.dict() 언패킹
    • ** 연산자는 item.dict()가 반환한 사전을 언패킹하여 함수에 개별적인 키워드 인수로 전달합니다.
    • {"item_id": item_id, **item.dict()} {"item_id": item_id, "name": "example", "description": "example item", "price": 10.0, "tax": 0.5}와 동일하게 동작합니다.
  • 최종 반환 값
    • 함수는 최종적으로 합쳐진 사전을 반환
    • 반환 값은 {"item_id": 1, "name": "example", "description": "example item", "price": 10.0, "tax": 0.5}
    • 만약 **item.dict()이 아닌 item.dict()을 사용했다면 {"item_id": 1, "item": {"name": "example", "description": "example item", "price": 10.0, "tax": 0.5}}

 

 

 

728x90
반응형