FastApi 사용하면서 기록할 것들
Embed
만약 Body 에서 Request Body 내부에 Key 로 구분지어서 받고 싶다면 Embed=True 로 설정하면 된다. 다음과 같이 나온다
from typing import Annotated
from fastapi import Body, FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Annotated[Item, Body(embed=True)]):
results = {"item_id": item_id, "item": item}
return results
이렇게 하면 아래와 같이 나온다.
{
"item": {
"name": "string",
"description": "string",
"price": 0,
"tax": 0
}
}
BaseModel로 QueryParam 사용하기
참고 자료
1. https://github.com/tiangolo/fastapi/discussions/6495
2. https://stackoverflow.com/questions/62468402/query-parameters-from-pydantic-model
Query parameters from pydantic model
Is there a way to convert a pydantic model to query parameters in fastapi? Some of my endpoints pass parameters via the body, but some others pass them directly in the query. All this endpoints s...
stackoverflow.com
만약 query param의 개수가 많다면 BaseModel로 선언하고, 아래와 같이 사용하면 된다.
class Foo(BaseModel):
num: int
char: str
@app.put("/items/{item_id}")
async def get_item(
query_parm: Foo = Depends(),
):
...
여기에 Field와 Query를 추가하면 metadata도 추가할 수 있다.
class Foo(BaseModel):
num: int = Field(
Query(
...,
description="숫자"
example=1,
),
)
char: str = Field(
Query(
...,
description="문자"
example="hello, world.",
min_length=1,
),
)
response_model_exclude_unset=True
값이 할당 되지 않은 예를 들면 Key가 없는 건 response 모델에서 뺀다.
class Item(BaseModel):
name: str
description: str | None = 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 모델은 Item으로 정의되어 있지만, response를 보면 key 가 없는 foo의 경우엔 보이지 않는다.
{
"name": "Foo",
"price": 50.2
}
Response Model Union
class BaseItem(BaseModel):
description: str
type: str
class CarItem(BaseItem):
type: str = "car"
class PlaneItem(BaseItem):
type: str = "plane"
size: int
items = {
"item1": {"description": "All my friends drive a low rider", "type": "car"},
"item2": {
"description": "Music is my aeroplane, it's my aeroplane",
"type": "plane",
"size": 5,
},
}
@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem])
async def read_item(item_id: str):
return items[item_id]
이런식으로 response_model을 선언하면 schema에선 다음과 같이 보인다.