쿼리 파라미터 (Query Parameters)
쿼리 파라미터 (Query Parameters)
경로 파라미터(path parameter)의 일부가 아닌 함수 파라미터를 선언하면, FastAPI는 그걸 자동으로 "쿼리" 파라미터로 해석해요.
from fastapi import FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]
쿼리(Query)는 URL에서 ? 뒤에 나오는 키-값 쌍의 모음이고, 각 쌍은 & 문자로 구분돼요.
예를 들어 다음 URL에서
http://127.0.0.1:8000/items/?skip=0&limit=10
쿼리 파라미터는 이렇게 돼요:
skip: 값이0limit: 값이10
쿼리 파라미터는 URL의 일부라서 "자연스럽게" 문자열로 처리돼요.
그런데 위 예시처럼 Python 타입(여기서는 int)으로 선언하면, 그 타입으로 변환되고 그 타입에 맞게 검증돼요.
경로 파라미터에 적용되던 과정은 쿼리 파라미터에도 그대로 적용돼요:
- 에디터 지원 (당연하게도)
- 데이터 "파싱(parsing)"
- 데이터 검증
- 자동 문서화
기본값 (Defaults)
쿼리 파라미터는 경로의 고정된 일부가 아니어서, 선택적(optional)일 수 있고 기본값도 가질 수 있어요.
위 예시에서 skip=0과 limit=10이 기본값이었죠.
그래서 이 URL로 접속하는 건
http://127.0.0.1:8000/items/
이 URL로 접속하는 것과 같아요:
http://127.0.0.1:8000/items/?skip=0&limit=10
하지만 예를 들어 이렇게 접속하면
http://127.0.0.1:8000/items/?skip=20
함수의 파라미터 값은 이렇게 돼요:
skip=20: URL에서 직접 설정했으니까limit=10: 기본값이니까
선택적 파라미터 (Optional parameters)
같은 방식으로, 기본값을 None으로 설정하면 선택적 쿼리 파라미터를 선언할 수 있어요:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
이 경우 함수 파라미터 q는 선택적이고, 기본값은 None이 돼요.
Tip
여기서 FastAPI가 경로 파라미터인 item_id와 아닌 q를 구분해 내는 것도 눈여겨보세요. q는 경로 파라미터가 아니니까 쿼리 파라미터로 처리돼요.
쿼리 파라미터 타입 변환 (Query parameter type conversion)
bool 타입도 선언할 수 있고, 변환이 적용돼요:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None, short: bool = False):
item = {"item_id": item_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
이 경우 이런 URL로 접속하면
http://127.0.0.1:8000/items/foo?short=1
또는
http://127.0.0.1:8000/items/foo?short=True
또는
http://127.0.0.1:8000/items/foo?short=true
또는
http://127.0.0.1:8000/items/foo?short=on
또는
http://127.0.0.1:8000/items/foo?short=yes
또는 대소문자를 바꾼 다른 어떤 조합(전부 대문자, 첫 글자만 대문자 등)이든, 함수는 short 파라미터를 불리언 값 True로 받아요. 그 외에는 False로 처리돼요.
여러 개의 경로·쿼리 파라미터 (Multiple path and query parameters)
경로 파라미터와 쿼리 파라미터를 동시에 여러 개 선언할 수 있고, FastAPI는 어떤 게 어떤 건지 구분해요.
그리고 특정 순서로 선언할 필요도 없어요. 이름으로 구분되거든요:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(
user_id: int, item_id: str, q: str | None = None, short: bool = False
):
item = {"item_id": item_id, "owner_id": user_id}
if q:
item.update({"q": q})
if not short:
item.update(
{"description": "This is an amazing item that has a long description"}
)
return item
필수 쿼리 파라미터 (Required query parameters)
경로가 아닌 파라미터(지금까지는 쿼리 파라미터만 봤죠)에 기본값을 선언하면, 그 파라미터는 필수가 아니에요.
특정 값을 넣지 않고 그냥 선택적으로 만들고 싶다면 기본값을 None으로 설정하면 돼요.
하지만 쿼리 파라미터를 필수로 만들고 싶다면, 기본값을 선언하지 않기만 하면 돼요:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
item = {"item_id": item_id, "needy": needy}
return item
여기서 쿼리 파라미터 needy는 str 타입의 필수 쿼리 파라미터예요.
브라우저에서 이런 URL을 열면
http://127.0.0.1:8000/items/foo-item
필수 파라미터인 needy를 넣지 않았으니 이런 오류를 보게 돼요:
{
"detail": [
{
"type": "missing",
"loc": [
"query",
"needy"
],
"msg": "Field required",
"input": null
}
]
}
needy는 필수 파라미터니까 URL에 설정해 줘야 해요:
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
이렇게 하면 제대로 동작해요:
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
그리고 당연히, 필수인 파라미터와 기본값이 있는 파라미터, 완전히 선택적인 파라미터를 섞어서 선언할 수도 있어요:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_user_item(
item_id: str, needy: str, skip: int = 0, limit: int | None = None
):
item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
return item
이 경우 쿼리 파라미터가 3개 있어요:
needy: 필수strskip: 기본값이0인intlimit: 선택적int
Tip
경로 파라미터에서 했던 것과 같은 방식으로 Enum도 사용할 수 있어요.