이제 모든 parameter들의 선언 방법에 대해 알아보았으니, 아래의 코드를 보며 어떤 parameter인지 보자.
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int = Path(..., title="The ID of the item to get", ge=0, le=1000),
q: Optional[str] = None,
item: Optional[Item] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
return results
item_id
: path parameter (required) → URL 에 명시q
: query parameter (optional) → URL X, Pydantic Model Xitem
: request body (optionval) → URL X, Pydantic Model Orequest body에 필요한 parameter들이 여러개일때는 아래와 같이 선언할 수 있다.
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
class User(BaseModel):
username: str
full_name: Optional[str] = None
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, user: User):
results = {"item_id": item_id, "item": item, "user": user}
return resul
위와 같이 선언되면, request body의 내용은 아래와 같은 형식이 되어야한다.
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
}
}
Fast API는 해당 json 형식을 파악하여 자동으로 Item
과 User
model로 converting과 validation check을 하며 바꾸게 된다.
Request Body는 Pydantic 모델을 설정하여 해당 Type을 명시하여 받는 것으로 Body parameter로 판단했다.
하지만 여러개의 변수를 캡슐화한 Pydantic 모델이 아닌, 단일 변수로 받고 싶을 때는 어떻게 해야될까?
이를 위해 Fast API는 Body
라는 것이 존재한다.
from fastapi import Body, FastAPI
@app.put("/items/{item_id}")
async def update_item(
*,
item_id: int,
item: Item,
user: User,
importance: int = Body(..., gt=0),
q: Optional[str] = None
):
results = {"item_id": item_id, "item": item, "user": user, "importance": importance}
if q:
results.update({"q": q})
return results
Query
/Path
와 똑같이 metadata 또한 설정할 수 있다. 위와 같이 선언될 경우 request body는 아래와 같은 형식이다.
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
},
"user": {
"username": "dave",
"full_name": "Dave Grohl"
},
"importance": 5
}
만약 request body parameter로 단 하나의 모델만이 필요할 때는 embed
변수를 True
로 하여 body 구조를 바꿀 수 있다.
이전의 구조는 아래와 같았다면,
{
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item = Body(..., embed=True)):
results = {"item_id": item_id, "item": item}
return results
embed=True
로 설정해준 뒤의 구조는 아래처럼 된다.
{
"item": {
"name": "Foo",
"description": "The pretender",
"price": 42.0,
"tax": 3.2
}
}
Pydantic 모델 또한 validation이나 meatadata를 추가할 수 있다.
먼저 pydantic 모듈에서 Field를 import 한다.
from pydantic import BaseModel, Field
이후, metadata나 validation 조건을 설정해주고 싶은 필드에 작성하면 된다.
class Item(BaseModel):
name: str
description: Optional[str] = Field(
None, title="The description of the item", max_length=300
)
price: float = Field(..., gt=0, description="The price must be greater than zero")
tax: Optional[float] = None
Query, Path, Body 모두 같은 역할을 하는 것이다.
Fast API 공식 문서에 따르면, Query, Path는 함수라고 한다. Pydantic의 FieldInfo 클래스의 하위 클래스인 Param의 객체를 생성하여 return한다고 한다. 반면에 Body나 Field는 FieldInfo 클래스 객체 생성자이며, 위의 함수들과는 엄밀히 보자면 다르다고 한다.