Fast API에서는 response_model
이라는 인자로 손쉽게 데이터를 정형화하여 내보낼 수 있다. response model은 pydantic으로 정의된 모델이나 이를 담는 데이터 형식이 될 수 있다.
from typing import List, Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
tags: List[str] = []
@app.post("/items/", response_model=Item)
async def create_item(item: Item):
return item
path operation 부분인 app.post
의 인자로 response_model=Item
이라고 명시하여 create_item
의 return 값이 Item
에 정의된 형식에 맞춰서 내보내지게 된다.
만약 Item
이 담긴 리스트를 내보내고 싶다면, List[Item]
처럼 정의하면 된다.
또한, create_item
함수가 Item
모델에서 선언한 필드나 타입 이외에 더 많은 데이터를 가지고 있더라도, 모델에 선언된 데이터만 내보내지게 된다.
즉, response_models
은
의 이점을 가진다.
아래는 유저 모델을 가지고 작성한 예제이다.
from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: Optional[str] = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: Optional[str] = None
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn):
return user
UserIn
모델은 response body로 들어오며 새로운 유저를 만들기 위한 폼이다. 반면에 UserOut
모델은 생성된 유저에 대한 정보를 다시 클라이언트에게 보내게 되는 모델이다.
자세히 보면, password
는 내보내지 않는 것을 볼 수 있다.
위와같이 정의가 되면 /docs
에는 아래와 같이 자동으로 documenation이 되게 된다.
만약 response_model로 선택된 모델에 default 값이 선언되어 있는 필드가 있을 때를 생각해보자.
default 값을 api 함수에서 직접 바꾸지 않았을 때, 즉 default 값이 내보내지게 될 때 이러한 바뀌지 않은 값들을 제외시키는 방법이 있다.
그것이 바로 response_model_exclude_unset
이다.
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: float = 10.5
tags: List[str] = []
items = {
"foo": {"name": "Foo", "price": 50.2},
"bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
"baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}
@app.get("/items/{item_id}", response_model=Item, response_model_exclude_unset=True)
async def read_item(item_id: str):
return items[item_id]
위와 같이 response_model_exclude_unset=True
로 선언을 하면,
{
"name": "Foo",
"price": 50.2
}
이렇게 작성되지 않은 description
과 tax
, tags
는 제외되어 값이 보내지게 된다.
만약 default value와 똑같은 값을 작성하였으면, fast api는 놀랍게도 새로 씌워진 것으로 판단하고 이를 내보내게 된다.
default value와 똑같은 값이 써졌더라도, 같으면 내보내고 싶지 않을 때는
response_model_exclude_defaults=True
로,
None
인 값을 가진 필드를 제외하고 싶으면
response_model_exclude_none=True
로 선언하면 된다.
만약 이미 작성한 pydantic 모델에서 특정 필드만을 내보내고 싶거나, 혹은 특정 필드를 제외하고 나머지 필드를 내보내고 싶을 때, response_model_include
과 response_model_exclude
으로 선언할 수 있다.
이전까지와는 다르게 str
이나 set
(list
나 tuple
도 가능) 자료형이 들어가야하며, 필드 이름을 넣어야한다.
@app.get(
"/items/{item_id}/name",
response_model=Item,
response_model_include={"name", "description"},
)
async def read_item_name(item_id: str):
return items[item_id]
@app.get("/items/{item_id}/public", response_model=Item, response_model_exclude={"tax"})
async def read_item_public_data(item_id: str):
return items[item_id]
팬이에요