FastApi Validation check pydantic

최준호·2024년 1월 29일

FastAPI

목록 보기
4/9
post-thumbnail

🔴 pydantic

이전에 글에서 body를 통해 데이터를 입력하는 예제를 진행했다. 여기서 문제는 데이터를 입력 받을때 유효성 검사를 진행하지 않고 특별한 데이터 형태 없이 받아 저장하게 되면 보안에도 취야해지고 전송된 데이터를 저장하고 불러올때 같은 형식을 유지할 수 없을 수 있다.

FastApi에서 제공하는 pydantic을 사용하여 validation check를 진행해보자.

🟠 pydantic 예제

from fastapi import APIRouter
from pydantic import BaseModel

board_router = APIRouter()

board_list = []

class Board(BaseModel) :
    id: int
    subject: str
    content: str

... 기존 코드

@board_router.post("/v2/board")
def post(board: Board) -> dict:
    board_list.append(board)
    return {"message" : "success"}

다음과 같이 v2 post를 정의해주고 class를 정의해준뒤 내용을 다르게 요청해보자

🟢 실패하는 요청

{
    "id": 1,
    "subject" : "제목"
}

content 키값을 빼고 보내보았다.

{
    "detail": [
        {
            "type": "missing",
            "loc": [
                "body",
                "content"
            ],
            "msg": "Field required",
            "input": {
                "id": 1,
                "subject": "제목"
            },
            "url": "https://errors.pydantic.dev/2.5/v/missing"
        }
    ]
}

다음과 같이 missing > body > content 라는 내용으로 반환되며 실패가 된다.

그리고 내 입장에서는 특이한 422 에러가 발생하는데 해당 에러는

이 응답은 서버가 요청을 이해하고 요청 문법도 올바르지만 요청된 지시를 따를 수 없음을 나타냅니다.

라고 한다.

🟢 성공하는 요청

{
    "id": 1,
    "subject" : "제목",
    "content" : "내용"
}

content를 포함하는 내용으로 수정해서 요청하면

{
    "message": "success"
}

정상 반환이 된다!

🟠 중복 모델 사용

중복 모델 사용이란 객체 안에 다른 객체를 사용하는 부분이다.

🟢 코드로 작성

from fastapi import APIRouter
from pydantic import BaseModel

board_router = APIRouter()

board_list = []

class Member(BaseModel):
    id: int
    name: str

class Board(BaseModel):
    id: int
    subject: str
    content: str
    member: Member

@board_router.get("/board")
def get() -> dict:
    return {"list" : board_list}

@board_router.post("/board")
def post(board: dict) -> dict:
    board_list.append(board)
    return {"message" : "success"}

@board_router.post("/v2/board")
def post(board: Board) -> dict:
    board_list.append(board)
    return {"message" : "success"}

위 코드와 같이 Member class를 추가하여 넣어주면 된다.

🟢 실패하는 요청

{
    "id": 1,
    "subject" : "제목",
    "content" : "내용",
    "member" : {
        "id" : 1
    }
}

member에 name값을 빼서 보내보자.

{
    "detail": [
        {
            "type": "missing",
            "loc": [
                "body",
                "member",
                "name"
            ],
            "msg": "Field required",
            "input": {
                "id": 1
            },
            "url": "https://errors.pydantic.dev/2.5/v/missing"
        }
    ]
}

다음과 같이 에러가 나온다.

🟢 성공하는 요청

{
    "id": 1,
    "subject" : "제목",
    "content" : "내용",
    "member" : {
        "id" : 1,
        "name" : "준호"
    }
}

정상적으로 요청 후

{
    "list": [
        {
            "id": 1,
            "subject": "제목",
            "content": "내용",
            "member": {
                "id": 1,
                "name": "준호"
            }
        }
    ]
}

get 으로 board를 호출해서 확인하면 다음과 같이 확인해볼 수 있다!

0개의 댓글