Overview
- FastAPI에서 POST 요청 하는 방법에 대해 작성합니다.
- POST 데이터를 Pydantic을 이용한 Validation 방법에 대해 작성합니다.
- 기록 목적이며 알고 있는 부분과는 다른 부분도 있을 수 있다는 점 참고 바랍니다.
FastAPI에서 Body 검증은 Pydantic을 이용하여 쉽게 구현할 수 있습니다.
요청하는 Body를 클래스로 만들어서 BaseModel을 상속 받고 타입을 명시하면 해당 키에 대한 Validation을 수행합니다.
간단하게 아래와 같이 간단하게 Item 클래스와 POST 요청을 받는 코드를 작성 했습니다.
from fastapi import Body, FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: int
description: str | None
app = FastAPI()
@app.post("/item", response_model=Item)
def create_item(item: Item):
return item
위 Item 클래스를 통해서 우리가 전달 할 수 있는 데이터를 확인 할 수 있습니다.
- name: 문자열이면서 빈값이어선 안됩니다.
- price: 정수형이면서 빈값이어선 안됩니다.
- description: 문자열 또는 해당 키가 존재하지 않아도 됩니다.
그리고 요청 형식은 아래와 같이 작성할 수 있습니다.
- FastAPI가 굉장히 똑똑하다고 느끼는 테스트는 3번째 curl 호출에서 확인 할 수 있다.
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000,
"description": "This is Monitor"
}'
..
..
{"name":"Monitor","price":1000000,"description":"This is Monitor"}
# description 값을 넣지 않아도 정상적으로 응답한다.
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000
}'
..
..
{"name":"Monitor","price":1000000,"description":null}
# price가 문자열로 된 정수가 들어와도 이를 적절하게 Validation 을 수행한다.
curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": "1000000",
"description": "This is Monitor"
}'
..
..
{"name":"Monitor","price":1000000,"description":"This is Monitor"}
비정상적인 데이터를 요청할 경우 FastAPI에서 적절하게 Validation 수행 후 응답한다.
# name의 값이 정수형으로 들어갈 경우
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": 123,
"price": 1000000,
"description": "This is Monitor"
}'
..
..
{"detail":[{"type":"string_type","loc":["body","name"],"msg":"Input should be a valid string","input":123,"url":"https://errors.pydantic.dev/2.4/v/string_type"}]}
# price의 값이 문자열인 경우
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": "1000000a",
"description": "This is Monitor"
}'
..
..
{"detail":[{"type":"int_parsing","loc":["body","price"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"1000000a","url":"https://errors.pydantic.dev/2.4/v/int_parsing"}]}
# description의 경우 빈값으로 받는건 가능하지만 문자열이 아닌 다른 타입이 들어오는 경우에는 에러로 처리된다.
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000,
"description": 123
}'
..
..
{"detail":[{"type":"string_type","loc":["body","description"],"msg":"Input should be a valid string","input":123,"url":"https://errors.pydantic.dev/2.4/v/string_type"}]}
Item 클래스로부터 상속을 받아서 또 다른 모델을 생성할 수도 있다. 해당 클래스로 알 수 있는 정보는 아래와 같습니다.
- ItemWithTax에서 tax는 float형이며, Body에 있는 데이터다.
- 그 값은 0보다는 크며 10 미만이여야 한다.
from fastapi import Body, FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: int
description: str = None
class ItemWithTax(Item):
tax: float = Body(gt=0, lt=10)
app = FastAPI()
@app.post("/item", response_model=ItemWithTax)
def create_item(item: ItemWithTax):
return item
그러면 Validation을 수행하는지 검증을 해보겠습니다.
# tax를 추가하여 전송하면 정상적으로 응답합니다.
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000,
"description": "This is Monitor",
"tax": 1.5
}'
..
..
{"name":"Monitor","price":1000000,"description":"This is Monitor","tax":1.5}
비정상적인 요청을 할 경우 어떻게 응답을 하는지 확인해보겠습니다.
# tax를 포함한 데이터를 전송하지 않는 경우
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000,
"description": "This is Monitor"
}'
..
..
{"detail":[{"type":"missing","loc":["body","tax"],"msg":"Field required","input":{"name":"Monitor","price":1000000,"description":"This is Monitor"},"url":"https://errors.pydantic.dev/2.4/v/missing"}]}
# tax가 비정상적인 값인 경우
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000,
"description": "This is Monitor",
"tax": "1.5a"
}'
..
..
{"detail":[{"type":"float_parsing","loc":["body","tax"],"msg":"Input should be a valid number, unable to parse string as a number","input":"1.5a","url":"https://errors.pydantic.dev/2.4/v/float_parsing"}]}
# tax가 10 미만이 아닐 경우
> curl -v http://localhost:8080/item -H 'Content-Type: application/json' -d '{
"name": "Monitor",
"price": 1000000,
"description": "This is Monitor",
"tax": "10"
}'
..
..
{"detail":[{"type":"less_than","loc":["body","tax"],"msg":"Input should be less than 10","input":"10","ctx":{"lt":10.0},"url":"https://errors.pydantic.dev/2.4/v/less_than"}]}
FastAP에서 Pydantic과 Body의 간단한 사용법에 대해서 확인해봤습니다.
클래스로 모델을 정의해서 Body의 값에 대한 Validation을 수행을 한다는 것을 확인했습니다. 위의 Body에서는 간단하게 gt, lt를 이용하여 해당 값이 0보다는 크고 10보다 미만인 값을 확인하는 기능도 넣었습니다.
예제에는 들어가있지는 않지만 regex를 이용하거나, 문자열의 길이를 검사하는 기능도 있으니 기회가 있으시거나 사용하실 일이 있다면 사용해보시는 것도 좋을 것 같습니다.
그러나 복잡한 로직을 이용한 검증이 필요한 경우에는 Body의 기능만으로는 부족할 것이라고 생각합니다. 그래서 FastAPI는 커스텀으로 검증을 수행할 수 있는 기능을 제공합니다. 다음 글에서는 그 기능에 대해서 다뤄보도록 하겠습니다. 이상입니다.
'FastAPI' 카테고리의 다른 글
[FastAPI] Depends를 이용한 Validation (0) | 2024.02.28 |
---|---|
[FastAPI] Simple FastAPI (0) | 2024.01.13 |