콘텐츠로 이동

쿼리 매개변수

경로 매개변수의 일부가 아닌 다른 함수 매개변수를 선언하면 "쿼리" 매개변수로 자동 해석합니다.

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]

쿼리는 URL에서 ? 후에 나오고 &으로 구분되는 키-값 쌍의 집합입니다.

예를 들어, 아래 URL에서:

http://127.0.0.1:8000/items/?skip=0&limit=10

...쿼리 매개변수는:

  • skip: 값 0을 가집니다.
  • limit: 값 10을 가집니다.

URL의 일부이므로 "자연스럽게" 문자열입니다.

하지만 파이썬 타입과 함께 선언할 경우(위 예에서 int), 해당 타입으로 변환 및 검증됩니다.

경로 매개변수에 적용된 동일한 프로세스가 쿼리 매개변수에도 적용됩니다:

  • (당연히) 편집기 지원
  • 데이터 "파싱"
  • 데이터 검증
  • 자동 문서화

기본값

쿼리 매개변수는 경로에서 고정된 부분이 아니기 때문에 선택적일 수 있고 기본값을 가질 수 있습니다.

위 예에서 skip=0limit=10은 기본값을 갖고 있습니다.

그러므로 URL로 이동하는 것은:

http://127.0.0.1:8000/items/

아래로 이동하는 것과 같습니다:

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: 기본값이기 때문입니다

선택적 매개변수

같은 방법으로 기본값을 None으로 설정하여 선택적 매개변수를 선언할 수 있습니다:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[str, None] = None):
    if q:
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id}

이 경우 함수 매개변수 q는 선택적이며 기본값으로 None 값이 됩니다.

확인

FastAPIitem_id가 경로 매개변수이고 q는 경로 매개변수가 아닌 쿼리 매개변수라는 것을 알 정도로 충분히 똑똑합니다.

참고

FastAPI는 q= None이므로 선택적이라는 것을 인지합니다.

Union[str, None]에 있는 Union은 FastAPI(FastAPI는 str 부분만 사용합니다)가 사용하는게 아니지만, Union[str, None]은 편집기에게 코드에서 오류를 찾아낼 수 있게 도와줍니다.

쿼리 매개변수 형변환

bool 형으로 선언할 수도 있고, 아래처럼 변환됩니다:

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: Union[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

이 경우, 아래로 이동하면:

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

또는 다른 어떤 변형(대문자, 첫글자만 대문자 등)이더라도 함수는 매개변수 bool형을 가진 short의 값이 True임을 압니다. 그렇지 않은 경우 False입니다.

여러 경로/쿼리 매개변수

여러 경로 매개변수와 쿼리 매개변수를 동시에 선언할 수 있으며 FastAPI는 어느 것이 무엇인지 알고 있습니다.

그리고 특정 순서로 선언할 필요가 없습니다.

매개변수들은 이름으로 감지됩니다:

from typing import Union

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: Union[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)이지 않았습니다.

특정값을 추가하지 않고 선택적으로 만들기 위해선 기본값을 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

여기 쿼리 매개변수 needystr형인 필수 쿼리 매개변수입니다.

브라우저에서 아래와 같은 URL을 연다면:

http://127.0.0.1:8000/items/foo-item

...필수 매개변수 needy를 넣지 않았기 때문에 아래와 같은 오류를 보게 됩니다:

{
    "detail": [
        {
            "loc": [
                "query",
                "needy"
            ],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

needy는 필수 매개변수이므로 URL에 반드시 설정해줘야 합니다:

http://127.0.0.1:8000/items/foo-item?needy=sooooneedy

...아래처럼 작동합니다:

{
    "item_id": "foo-item",
    "needy": "sooooneedy"
}

그리고 물론, 일부 매개변수는 필수로, 다른 일부는 기본값을, 또 다른 일부는 선택적으로 선언할 수 있습니다:

from typing import Union

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: Union[int, None] = None
):
    item = {"item_id": item_id, "needy": needy, "skip": skip, "limit": limit}
    return item

위 예시에서는 3가지 쿼리 매개변수가 있습니다:

  • needy, 필수적인 str.
  • skip, 기본값이 0int.
  • limit, 선택적인 int.

경로 매개변수와 마찬가지로 Enum을 사용할 수 있습니다.