프레임워크/FastAPI

[FastAPI] FastAPI [14] Response model - Return Type

:) :) 2023. 4. 25. 13:06

https://fastapi.tiangolo.com/ko/tutorial/response-model/

 

Response Model - Return Type - FastAPI

Response Model - Return Type Warning The current page still doesn't have a translation for this language. But you can help translating it: Contributing. You can declare the type used for the response by annotating the path operation function return type. Y

fastapi.tiangolo.com

<FastAPI 공식문서 참조>

 

 

1. Response Model - Return Type

 

return type을 지정해줌으로써 response에 사용되는 유형을 선언할 수 있다.

 

async def create_item(item:Item) -> Item

-> 키워드를 통해 지정 가능하다.

Pydantic models, lists, dictionaries, scalar values 등 모든것이 return type으로 가능하다.

 

 

 

2. response_model Parameter

선언은 Pydantic model로 했지만 Dictionary를 return 받고싶은 경우가 있을 수 있다.

이럴 때 response_model Parameter를 이용하여 해당 요구를 수행할 수 있다.

 

반환유형 주석을 달아놓으면 (사실상 맞는) error를 편집기가 알려줄 것이다.

 

 다음과 같은 예시로 사용한다.

from typing import Any

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


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


@app.post("/items/", response_model=Item)
async def create_item(item: Item) -> Any:
    return item


@app.get("/items/", response_model=list[Item])
async def read_items() -> Any:
    return [
        {"name": "Portal Gun", "price": 42.0},
        {"name": "Plumbus", "price": 32.0},
    ]

 

3. response_model Priority

 return type과 response_model을 동시에 선언하게 되면,

response_model 매개변수가 처리 우선순위를 가진다.

 또한 response_model=None을 사용하여 해당 경로 작업에 대한 응답 모델 생성을 비활성화할 수 있다. 유효한 Pydantic 필드가 아닌 항목에 대한 유형 주석을 추가하는 경우에 이를 사용한다.

 

 

4. Return the same input data

 아래의 예시를 보자. 일반 텍스트 비밀번호를 포함한 UserIn model을 선언하고 있다.

* emailstr을 사용하려면 우선 pip install email-validator부터 하자.

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    full_name: str | None = None


# Don't do this in production!
@app.post("/user/")
async def create_user(user: UserIn) -> UserIn:
    return user

브라우저가 비밀번호로 사용자를 만들어낼 때마다, API는 동일한 비밀번호를 응답해줄 것이다.

로그인과정에선 이는 별 문제가 되지 않는게 동일한 사용자가 비밀번호를 서버로 보내기 때문이다.

그러나 다른 경로작업에 이를 사용하면 모든 사용자에게 비밀번호를 보내버릴 수도 있게 된다.

 

 

4-1. Add an output model

 input model의 문제점을 보완하기 위해 output model을 만들어 보자.

from typing import Any

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    full_name: str | None = None


class UserOut(BaseModel):
    username: str
    email: EmailStr
    full_name: str | None = None


@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:
    return user

 여기서 경로작업이 비밀번호를 포함하는 동일한 사용자를 반환하더라도

 

UserOut type이 되는 response_model을 선언함으로써 비밀번호를 포함하지 않게 할 수 있다.

 

 

4-2. response_model or Return Type

  그래도 결국엔 return type과는 다른 type의 자료(UserOut)를 응답하기 때문에 편집기는 에러를 내면서 불평할 수 있다.

이를 분명히 해결하는 방법이 아래에 서술되어있다.

 

 

 

5. Return Type and Data Filtering

 클래스 및 상속을 활용하여 여러 이점을 챙겨보자.

from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class BaseUser(BaseModel):
    username: str
    email: EmailStr
    full_name: str | None = None


class UserIn(BaseUser):
    password: str


@app.post("/user/")
async def create_user(user: UserIn) -> BaseUser:
    return user

 

여러 당연한 이점들이 존재한다.

  • 자료형 주석 및 도구
    •  UserIn은 BaseUser과 BaseModel의 모든 field를 사용할 수 있다.
    •  마지막 함수의 return type이BaseUser이나, 이는 사실상 UserIn을 return한다.
    • UserIn은 BaseUser의 sub class이기 때문이다.
    •  

 

 

6. Referece

https://fastapi.tiangolo.com/ko/tutorial/response-model/