본문 바로가기

웹 프레임워크/FastAPI

FastAPI - 03 (쿼리(Query) 매개변수)

출처: https://fastapi.tiangolo.com/tutorial/query-params/
아래의 내용은 공식 사이트의 내용을 제 경험과 생각을 추가하여 다시 정리한 것 입니다.

쿼리(Query) 매개변수 예시

경로 매개변수가 아닌 함수의 매개변수는 FastAPI에서 자동으로 쿼리(Query) 매개변수로 인식됩니다. 이는 함수에 선언된 매개변수가 URL의 경로 일부가 아니라면, 그 매개변수가 URL의 쿼리 스트링으로 처리된다는 의미입니다.

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): # skip, limit는 Query Parameter
    # fake_items_db 리스트를 slicing(skip:skip+limit)하여 반환
    return fake_items_db[skip : skip + limit]

skip, limit는 경로 매개변수에 선언 되지 않았으므로 쿼리 매개변수로 처리 됩니다.

아래는 쿼리 스트링이 포함된 URL의 예시 입니다.

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

URL에서 '?' 뒤에 오는 부분은 'key=value' 형식으로 구성된 쿼리 매개변수를 나타냅니다. 각 쿼리 매개변수는 '&'로 구분됩니다. 이 경우, 'skip'은 0값으로, 'limit'은 10값으로 설정된 쿼리 매개변수가 됩니다.

skip=0, limit=3 설정

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

skip=0, limit=3으로 설정되어 return fake_items_db[0:3]으로 처리 됩니다. 결과는 다음과 같습니다.

[{"item_name":"Foo"},{"item_name":"Bar"},{"item_name":"Baz"}]

skip=1, limit=2 설정

http://127.0.0.1:8000/items/?skip=1&limit=2

skip=1, limit=2으로 설정되어 return fake_items_db[1:3]으로 처리 됩니다. 결과는 다음과 같습니다.

[{"item_name":"Bar"},{"item_name":"Baz"}]

limit=2 만 설정

http://127.0.0.1:8000/items/?limit=2

skip은 기본 값 0으로, limit=2으로 설정되어 return fake_items_db[0:2]으로 처리 됩니다. 결과는 다음과 같습니다.

[{"item_name":"Foo"},{"item_name":"Bar"}]

skip, limt 둘다 설정하지 않음

http://127.0.0.1:8000/items/?limit=2

skip은 기본 값 0으로, limit도 기본값 10으로 설정되어 return fake_items_db[0:10]으로 처리 됩니다. 결과는 다음과 같습니다.

[{"item_name":"Foo"},{"item_name":"Bar"},{"item_name":"Baz"}]

None 타입 설정

쿼리 매개변수를 None 타입으로 설정 하여 선택적인 쿼리 매개변수를 만들 수 있습니다.

from typing import Union  # Union은 여러 타입 중 하나를 의미

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
# Union[str, None]은 str 또는 None 타입을 의미
# q: Union[str, None] = None 은 q 매개변수가 str 또는 None 타입이며, 기본값은 None이라는 의미
async def read_item(item_id: str, q: Union[str, None] = None):
    if q: # q가 None이 아니면 
        return {"item_id": item_id, "q": q}
    return {"item_id": item_id} # q가 None이면

q가 None이 아닌 경우

http://127.0.0.1:8000/items/foo?q=3

'item_id'는 경로 매개변수로 'foo'가 설정 되고, 'q'는 쿼리 매개변수로 3이 설정되어 return {"item_id": 'foo', "q": '3'}으로 처리 됩니다. 결과는 다음과 같습니다.

{"item_id":"foo","q":"3"}

q가 None인 경우

http://127.0.0.1:8000/items/foo

'item_id'는 경로 매개변수로 'foo'가 설정 되고, 'q'는 None이 설정되어 return {"item_id": 'foo'}으로 처리 됩니다. 결과는 다음과 같습니다.

{"item_id":"foo"}

bool 타입 설정

쿼리 매개변수를 bool 타입으로 설정 할 수 있으며 여러 유형의 값으로 bool 타입으로 변경 됩니다.

from typing import Union  # Union은 여러 타입 중 하나를 의미

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
# qshort: bool = False는 short 매개변수가 bool 타입이며, 기본값은 False이라는 의미
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: # short가 False이면
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

short가 True인 경우

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
# 등...

결과는 다음과 같습니다.

{"item_id":"foo"}

short가 False인 경우

http://127.0.0.1:8000/items/foo
# 또는
http://127.0.0.1:8000/items/foo?short=Fasle
# 또는
http://127.0.0.1:8000/items/foo?short=false
# 또는
http://127.0.0.1:8000/items/foo?short=off
# 또는
http://127.0.0.1:8000/items/foo?short=no
# 등...

결과는 다음과 같습니다.

{"item_id":"foo","description":"This is an amazing item that has a long description"}

여러 개의 경로/쿼리 매개변수

FastAPI는 함수에 선언된 매개변수의 이름을 통해 경로 매개변수와 쿼리 매개변수를 자동으로 구분합니다. 이를 통해 여러 경로 및 쿼리 매개변수를 하나의 함수에서 효과적으로 처리할 수 있습니다.

from typing import Union

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}/items/{item_id}")  # 2개의 경로 매개변수(user_id, item_id)
async def read_user_item(
    # 2개의 쿼리 매개변수(q, short)
    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
http://127.0.0.1:8000/users/123/items/foo?q=q&short=0

위의 URL은 다음과 같은 결과를 반환합니다.

{
  "item_id": "foo",
  "owner_id": 123,
  "q": "q",
  "description": "This is an amazing item that has a long description"
}

필수 쿼리 매개변수

쿼리 매개변수를 필수로 설정하려면, 기본값(None 포함)을 설정하지 않으면 됩니다.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
# needy에 기본 값을 설정 하지 않음 -> 필수 쿼리 매개변수
async def read_user_item(item_id: str, needy: str):   
    item = {"item_id": item_id, "needy": needy}
    return item

needy 설정

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

위의 URL은 다음과 같은 결과를 반환합니다.

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

needy 설정 하지 않음

http://127.0.0.1:8000/items/foo

위의 URL은 다음과 같은 결과를 반환합니다.

{
  "detail": [
    {
      "type": "missing",
      "loc": [
        "query",
        "needy"
      ],
      "msg": "Field required",
      "input": null,
      "url": "https://errors.pydantic.dev/2.1/v/missing"
    }
  ]
}