본문 바로가기
Fast API/fastapi배우기

Fast API 배우기 11부 - Response Model

by 붕어사랑 티스토리 2021. 11. 1.
반응형

response_model 을 이용하여 아래의 operation들에 관한 response model을 지정해 줄 수 잇씁니다.

 

  • @app.get()
  • @app.post()
  • @app.put()
  • @app.delete()
  • etc.
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
@app.post("/items/", response_model=Item)

 

 

여기서 주목할것은 함수의 인풋이 아닌 decoration의 인풋이라는 것입니다.

response_model은 다음과 같은 경우에 쓰입니다.

 

  • 아웃풋 데이타를 response_model에서 지정한 모델로 변환
  • reponse에 JSON 스키파 추가
  • doc시스템에 사용

 

그러나 가장 중요한건 아래 내용입니다.

  • 아웃풋 데이터자료형을 지정된 모델로 제한

 

 

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

위 예제는 유저가 아이디와 패스워드를 입력하면 그대로 돌려주는 api 입니다.

단 password까지 돌려주면 문제가 생기겠지요? 그래서 UserOut이라는 response_model을 따로 만들어 적용해 주었습니다.

 

반응형

 

Response Model encoding parameters

 

response model은 아래와같이 초기값을 가질 수 있습니다.

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: 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]

 

위 Item 모델은 아래와 같은 default value를 가집니다.

  • description: Optional[str] = None 
  • tax: float = 10.5
  • tags: List[str] = []

 

그런데 만약 이러한 default value를 response에 담아서 보내기 싫다면 response_model_exclude_unset=True 로 지정해줍니다.

 

 

만약 path parameter로 foo가 왔다고 가정합니다.

 

default value를 exclude 해버리면 다음과 같이 reponse가 작성됩니다.

{
    "name": "Foo",
    "price": 50.2
}

 

bar와 baz 리스폰스도 넣어 볼 테니 함께 비교해 보세요.

{
    "name": "Bar",
    "description": "The bartenders",
    "price": 62,
    "tax": 20.2
}

bar의 경우 description과 tax에 값이 set되어 제외되지 않았습니다.

 

{
    "name": "Baz",
    "description": None,
    "price": 50.2,
    "tax": 10.5,
    "tags": []
}

baz의 경우 특이하게 tags가 default value와 같이 []로 set되었는데 제외되지 않았습니다.

 

 

 

 

 

response_model_include & response_model_exclude

 

위 두 키워드로 response 모델의 필드를 include할지 exclude할지 결정 할 수 있습니다.

 

방법은 str로 이루어진 set을 입력해주면 됩니다.

 

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


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


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
    "baz": {
        "name": "Baz",
        "description": "There goes my baz",
        "price": 50.2,
        "tax": 10.5,
    },
}


@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]
response_model_include={"name", "description"}
response_model_exclude={"tax"}

 

 

 

또한 set대신에 list나 tuple을 이용하여 입력도 가능합니다.

 

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


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


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The Bar fighters", "price": 62, "tax": 20.2},
    "baz": {
        "name": "Baz",
        "description": "There goes my baz",
        "price": 50.2,
        "tax": 10.5,
    },
}


@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]
response_model_include=["name", "description"]
response_model_exclude=["tax"]

 

반응형

댓글