프레임워크/FastAPI

[FastAPI] FastAPI [3] - Request Body

:) :) 2023. 3. 13. 00:16

https://fastapi.tiangolo.com/ko/tutorial/body/

 

Request Body - FastAPI

Request Body Warning The current page still doesn't have a translation for this language. But you can help translating it: Contributing. When you need to send data from a client (let's say, a browser) to your API, you send it as a request body. A request b

fastapi.tiangolo.com

<FastAPI 공식문서 참조>

 

 

1. Request Body

  • Request Body
    • 클라이언트가 내 API에 보내는 데이터
  • Response Body
    • 내 API가 클라이언트에게 보내는 데이터

 내 API는 거의 항상 response body를 보내야 한다. 그러나 클라이언트는 항상 request body를 보내지 않아도 된다.

Request Body를 선언하기 위해,  Pydantic  모델을 사용하자(pydantic의 모든 이점과 능력을 적극적 이용!).

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/")
def create_item(item: Item):
    return item

* Python 3.10이후부터는 Union을 사용하지 않고 | 연산자 하나만으로 Union의 역할을 대체할 수 있다.

 BaseModel의 상속을 통해 내 데이터 모델을 선언하였다(None 키워드를 통해 Optional or required parameter인지 구분).

 

이 모델은, 아래 JSON  object  혹은 Python  dict  자료를 받을 수 있다.

{
    "name": "Foo",
    "description": "An optional description",
    "price": 45.2,
    "tax": 3.5
}

 

경로 동작을 위해  path, query parameter을 선언한 방법처럼 쓸 수 있다.

@app.post("/items/")
def create_item(item: Item):
    return item

해당 예제는 post로 mapping 했으므로 URL로 테스트하기 까다로워, Swagger UI 사이트에서 확인해보자.

해당 item의 각 데이터를 입력하고 Execute 했더니 다음과 같은 오류가 나왔다.

 

{
  "detail": [
    {
      "loc": [
        "body",
        77
      ],
      "msg": "Expecting property name enclosed in double quotes: line 4 column 14 (char 77)",
      "type": "value_error.jsondecode",
      "ctx": {
        "msg": "Expecting property name enclosed in double quotes",
        "doc": "{\n  \"name\": \"display\",\n  \"description\": \"display_for_computer\",\n  \"price\": 1,000.0,\n  \"tax\": 10.0\n}",
        "pos": 77,
        "lineno": 4,
        "colno": 14
      }
    }
  ]
}

double quotes를 작성하여 오류가 발생했다고 나왔다. FastAPI의 error msg는 참 친절한 것 같다.

수정 후 다시 execute해 본 결과,

 

{
  "name": "display",
  "description": "display_for_computer",
  "price": 1000,
  "tax": 10
}

잘 나온다.

이 파이썬 타입 선언 이후, Fast API는 :

  • request body를 JSON으로 읽는다.
  • 데이터 유효성 검정
  • 파라미터에 추천하는 데이터 타입을 준다
  • JSON Schema 정의를 생성한다.
    • 이 스키마는 생성된  OpenAPI schema의 일부가 되고, 자동 Uls 문서에 의해 사용된다.

 

 

 

내 모델의 JSON scheme는 OpenAPI의 일부가 되고. 이는 아래의 interactive API docs에 보인다.
그리고 이들을 사용하는 모든 path operation 속에도 보이게 된다.

 

1-1. Use the model

 함수 내부에서도 모든 모델 객체의 속성을 직접 접근할 수 있다.

dict으로 받아와 데이터를 추가한 뒤 업데이트 할 수 있다.

@app.post("/items/")
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

 

1-2. Request body + path parameters

 동시에 선언할 수도 있다.

@app.put("/items/{item_id}")
def create_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를 제외한 매개변수가 단일 타입이면 query parameter로 해석된다.
  •  매개변수가 Pydantic model의 일종으로 선언되면, Request body로 해석된다.