Post

FastAPI 공식문서 따라하기[5] - Request Body

https://fastapi.tiangolo.com/ko/ 공식문서 따라하는 글

☑️ 1. Request Body

  • clientserver쪽으로 보내는 데이터를 requestbody라고 한다.

  • responsebodyserverclient쪽으로 보내는 데이터를 말한다.

  • request body는 Pydantic이 가지고 있는 혜택을 통해 더 유연하게 동작할 수 있다.

데이터를 보낼땐 GET 을 쓰지 않는것이 좋습니다. GET을 조회용으로만 쓰는것이 HTTP 명세입니다.


☑️ 2. Import Pydantic’s BaseModel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


app = FastAPI()


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

Item라고 선언한 클래스는 BaseModel에 의해 상속받고 있다.

None이라고 초기값을 준 것은 필수로 받아야하는 값이 아니다. 그러나 None을 명시하지 않으면 그 값은 필수로 받아야한다.

즉 다음과 같은 데이터도 허용한다는 것이다.

1
2
3
4
{
    "name" : "kms"
    "price" : 45.2
}

description 속성과 tax속성에는 아무값도 주지 않아도 된다는 것이다.


☑️ 3. 결과

FastAPI는 다음과 같이 프로세스를 진행한다.

  1. request에서 JSON으로 데이터를 읽는다,
  2. 데이터의 형식에 맞게 타입을 변환한다.(필요시)
  3. 데이터를 검증한다
    • 만약 데이터가 유효하지 않다면 clear error를 리턴하며 정확히 어떤 데이터가 문제인지 명시해준다
  4. 파라미터에 있는 item을 받아 온다.

    만약 Item의 매개변수들을 선언하였다면, 편집기에서 자동완성 기능을 사용할 수 있다.

  1. 프로그래머가 작성한 클래스 모델에 맞춰 JSON Schema를 만들어 낸다.
  2. schemas는 생성된 OpenAPI schema의 일부가 되고, Swagger와 같은 자동완성 문서에 사용된다.


☑️ 4. Model 활용법

정의한 클래스의 속성값에 맞게 접근 할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = 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({"item price with tax : " : price_with_tax})
    return item_dict


☑️ 5. Request Body + path parameter

request bodypath parameter를 같이 사용할 수 있다.

FastAPI를 사용할때 path parameter경로에서 받아야하고 model을 받을때는 request body에서 받아야합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


app = FastAPI()

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

결과

Swagger에서 테스트 진행.

1
2
3
4
5
6
7
8
9
10
11
#curl
curl -X 'PUT' \
  'http://localhost:8000/items/5' \
  -H 'accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "price": 0,
  "tax": 0
}'
1
2
3
4
5
6
7
{
  "item_id": 5,
  "name": "string",
  "description": "string",
  "price": 0,
  "tax": 0
}

☑️ 6. Request Body + path parameter + query parameters

세 가지를 짬뽕하면 어떻게 해야할까

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None
    price: float
    tax: Optional[float] = None


app = FastAPI()

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

FastAPI는 놀랍게도 이 모든것을 정확하게 인지하고 데이터를 넣어준다.

어떻게 하는걸까?

  • 만약 경로에 파라미터가 선언되어있다면 이는 path parameter로 인지한다.
  • 만약 sigular type(int,float등..)타입이면 query parameter로 인지한다.
  • 만약 Pydantic model타입으로 파라미터가 선언되어 있으면 이는 request body로 인지한다.

Pydantic model을 사용하지 않는다면 Body Parametes에 넣는 방법도 있다.

https://fastapi.tiangolo.com/ko/tutorial/body-multiple-params/#singular-values-in-body

This post is licensed under CC BY 4.0 by the author.