[FastAPI 공식문서] FastAPI - (8) 쿼리 매개변수와 문자열 검증 & 경로 매개변수와 숫자 검증

이영락·2024년 10월 11일

개발자 기본기

목록 보기
42/53

🏖️ FastAPI에서 쿼리 매개변수와 문자열 검증

쿼리 매개변수는 API의 경로가 아닌, URL의 ? 뒤에 위치하며, FastAPI는 이를 쉽게 처리할 수 있습니다. Query 클래스를 사용하면 쿼리 매개변수에 대한 검증과 추가 정보를 선언할 수 있습니다.


1. 기본 쿼리 매개변수 사용

쿼리 매개변수는 선택적이거나 필수적일 수 있으며, 기본값을 설정할 수도 있습니다.

from typing import Union
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
async def read_items(q: Union[str, None] = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • qOptional[str]로 선언되어 있으며, 기본값은 None입니다.
  • URL 예시: http://127.0.0.1:8000/items/?q=search
    • 쿼리 매개변수 q는 선택적이며, 값이 없으면 None으로 처리됩니다.

2. Query 클래스를 사용한 추가 검증

쿼리 매개변수에 추가적인 검증을 선언하려면 Query 클래스를 사용합니다. 이를 통해 문자열의 길이 제한, 정규표현식, 기본값 등을 설정할 수 있습니다.

2.1 기본 예시: max_length 사용

from fastapi import FastAPI, Query
from typing import Union

app = FastAPI()

@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • max_length=50: q의 길이를 50자 이하로 제한합니다.
    • http://127.0.0.1:8000/items/?q=verylongstring으로 50자를 넘는 값을 입력하면 ValidationError가 발생합니다.

2.2 min_length와 max_length 검증 추가

@app.get("/items/")
async def read_items(
    q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • min_length: q는 최소 3자 이상이어야 합니다.
  • max_length: q는 최대 50자까지 입력할 수 있습니다.

3. 정규표현식(Regex) 검증

정규표현식을 사용하여 쿼리 매개변수의 값이 특정 패턴과 일치하는지 검증할 수 있습니다.

@app.get("/items/")
async def read_items(
    q: Union[str, None] = Query(default=None, min_length=3, max_length=50, pattern="^fixedquery$"),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • pattern="^fixedquery$": q 값이 정확히 "fixedquery"와 일치해야 합니다.
    • 정규표현식 ^: 문자열의 시작.
    • 정규표현식 $: 문자열의 끝.
    • http://127.0.0.1:8000/items/?q=fixedquery로 호출하면 성공, 다른 값은 검증 오류 발생.

4. 기본값 설정

기본값을 설정하면 쿼리 매개변수가 제공되지 않을 때 해당 기본값이 사용됩니다.

@app.get("/items/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • 기본값 "fixedquery": 쿼리 매개변수가 없을 때 기본적으로 이 값을 사용합니다.
  • http://127.0.0.1:8000/items/로 호출하면 q="fixedquery"가 사용됩니다.

5. 필수 쿼리 매개변수

쿼리 매개변수를 필수로 만들려면 ...를 사용합니다. 이는 파이썬의 Ellipsis로, 기본값이 없다는 의미로 사용됩니다.

@app.get("/items/")
async def read_items(q: str = Query(..., min_length=3)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • q는 필수로 선언되며, 기본값이 없습니다.
  • Ellipsis(...)는 이 매개변수가 필수임을 의미합니다.

6. 쿼리 매개변수로 리스트 받기

쿼리 매개변수를 리스트로 받을 수도 있습니다. Query를 명시적으로 사용하여 여러 값을 처리합니다.

from typing import List, Union
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
    return {"q": q}
  • URL 예시: http://127.0.0.1:8000/items/?q=foo&q=bar
    • 여러 쿼리 매개변수를 리스트로 받을 수 있습니다.
  • 응답 예시:
{
  "q": ["foo", "bar"]
}

7. 추가 메타데이터 선언

쿼리 매개변수에 대한 추가 정보를 선언할 수 있습니다. 이러한 정보는 OpenAPI 스키마에 포함되어 문서화됩니다.

7.1 title과 description 사용

@app.get("/items/")
async def read_items(
    q: Union[str, None] = Query(
        default=None, 
        title="Query string", 
        description="Query string for the items to search in the database.",
        min_length=3,
    ),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • title: 쿼리 매개변수에 대한 제목을 설정합니다.
  • description: 매개변수의 설명을 추가하여 API 문서에 표시됩니다.

8. 별칭(Alias) 사용

파이썬 변수로 사용할 수 없는 이름을 쿼리 매개변수로 사용할 경우 alias를 사용하여 다른 이름으로 처리할 수 있습니다.

@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • alias="item-query": item-query라는 쿼리 매개변수를 사용할 수 있습니다.
  • URL 예시: http://127.0.0.1:8000/items/?item-query=foobar

9. 사용 중지된(deprecated) 매개변수

사용하지 않는 쿼리 매개변수를 표시하려면 deprecated=True를 설정할 수 있습니다.

@app.get("/items/")
async def read_items(
    q: Union[str, None] = Query(
        default=None, 
        alias="item-query", 
        deprecated=True,
        min_length=3, 
        max_length=50
    ),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
  • deprecated=True: 문서에 이 매개변수가 더 이상 사용되지 않음을 표시합니다.

10. 요약

  • Query 클래스를 사용

하여 쿼리 매개변수에 대해 추가 검증 및 메타데이터를 정의할 수 있습니다.

  • min_length, max_length, pattern 등의 검증을 통해 매개변수 값을 제한할 수 있습니다.
  • list 형태로 여러 쿼리 매개변수를 받을 수 있으며, 기본값이나 필수 값을 설정할 수 있습니다.
  • title, description, alias와 같은 메타데이터를 사용하여 API 문서화가 가능하며, deprecated로 더 이상 사용되지 않는 매개변수를 표시할 수 있습니다.

🏖️ 경로 매개변수와 숫자 검증

FastAPI에서는 경로 매개변수에 대한 검증을 Path 클래스를 사용하여 설정할 수 있습니다. 이를 통해 경로 매개변수에 숫자 범위와 같은 제약을 추가하고, 메타데이터를 선언할 수 있습니다.


1. Path 임포트 및 기본 사용

경로 매개변수에 검증을 추가하기 위해 Path 클래스를 임포트합니다.

from fastapi import FastAPI, Path
from typing import Union

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
  • item_id: 경로 매개변수로, int 타입입니다.
  • title="The ID of the item to get": 경로 매개변수에 대한 설명을 추가하여 자동 문서화에 포함됩니다.

2. 경로 매개변수 필수성

경로 매개변수는 경로 자체의 일부이기 때문에 항상 필수적입니다. 기본값을 설정하거나 None으로 선언해도 필수로 간주됩니다.

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = None,
):
    return {"item_id": item_id}

3. 숫자 검증 추가

Path 클래스를 사용하여 경로 매개변수에 대한 숫자 검증을 설정할 수 있습니다.

3.1 숫자 범위 설정: ge, gt, le, lt

숫자 매개변수에 대해 다음과 같은 검증을 사용할 수 있습니다:

  • ge (greater than or equal): 주어진 값보다 크거나 같음.
  • gt (greater than): 주어진 값보다 큼.
  • le (less than or equal): 주어진 값보다 작거나 같음.
  • lt (less than): 주어진 값보다 작음.
@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get", ge=1, le=1000),
    q: Union[str, None] = None,
):
    return {"item_id": item_id}
  • item_id는 1 이상, 1000 이하의 값이어야 합니다.
  • 예시:
    • http://127.0.0.1:8000/items/5는 유효한 값.
    • http://127.0.0.1:8000/items/0ValidationError 발생.

3.2 경로 매개변수와 쿼리 매개변수의 혼합

숫자 검증을 적용한 경로 매개변수와 쿼리 매개변수를 함께 사용할 수 있습니다.

from fastapi import FastAPI, Path, Query
from typing import Union

app = FastAPI()

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get", ge=1, le=1000),
    q: Union[str, None] = Query(default=None),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
  • item_id는 1 이상, 1000 이하의 값이어야 합니다.
  • q는 쿼리 매개변수로, 선택적입니다.

4. 부동소수(float) 값에 대한 숫자 검증

숫자 검증은 float 값에 대해서도 동작합니다.

@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get", ge=1, le=1000),
    size: float = Query(gt=0, lt=10.5),
):
    return {"item_id": item_id, "size": size}
  • size는 0보다 크고, 10.5보다 작은 float 값이어야 합니다.
  • 예시:
    • http://127.0.0.1:8000/items/10?size=5.5는 유효.
    • http://127.0.0.1:8000/items/10?size=11ValidationError 발생.

5. 경로 매개변수 정렬

경로 매개변수는 항상 필수적이기 때문에, 기본값이 있는 쿼리 매개변수 앞에 필수 경로 매개변수를 배치해야 할 때가 있습니다. 하지만 매개변수를 재정렬해 경로 매개변수를 앞으로 배치할 수 있습니다.

@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: int = Path(title="The ID of the item to get", ge=1),
):
    return {"item_id": item_id, "q": q}
  • 여기서 q는 필수적인 쿼리 매개변수입니다.
  • item_id는 경로 매개변수로, 1 이상의 정수여야 합니다.

5.1 키워드 인자 사용 (매개변수 정렬)

경로 매개변수를 *로 표시해 매개변수의 순서를 명확하게 정의할 수 있습니다.

@app.get("/items/{item_id}")
async def read_items(
    *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):
    return {"item_id": item_id, "q": q}
  • *는 이후의 매개변수가 키워드 인자(키-값 쌍)로 전달됨을 의미합니다.
  • item_id는 경로 매개변수로, ge=1 제약이 있으며, q는 필수적인 쿼리 매개변수입니다.

6. 요약

  • Path 클래스를 사용하여 경로 매개변수에 검증 및 메타데이터를 추가할 수 있습니다.
  • 숫자 검증은 경로 매개변수에 대해서도 적용되며, ge, gt, le, lt 등을 통해 숫자 범위를 제한할 수 있습니다.
  • 경로 매개변수와 쿼리 매개변수를 함께 사용할 수 있으며, FastAPI는 매개변수를 구분하여 처리합니다.
  • float 타입의 매개변수에도 숫자 검증을 적용할 수 있습니다.
  • 매개변수의 순서가 중요한 경우, 키워드 인자(*)를 사용해 매개변수를 명확하게 정렬할 수 있습니다.

🏖️ Query Parameter Models

FastAPI에서는 여러 쿼리 매개변수가 관련된 경우, Pydantic 모델을 사용하여 이들을 하나의 그룹으로 선언할 수 있습니다. 이를 통해 여러 곳에서 모델을 재사용하거나, 한 번에 검증 및 메타데이터를 선언할 수 있습니다. 😎


1. Pydantic 모델을 사용한 쿼리 매개변수 선언

Pydantic 모델을 이용하여 쿼리 매개변수를 선언할 수 있습니다. 예를 들어, 필터링이나 정렬 같은 여러 매개변수가 필요할 때 Pydantic 모델로 쉽게 관리할 수 있습니다.

1.1 기본 예시

from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()

class FilterParams(BaseModel):
    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []

@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
    return filter_query
  • limit: 최대 100개의 항목을 반환하며, 값은 0보다 커야 합니다.
  • offset: 0 이상의 값으로 설정합니다.
  • order_by: created_at 또는 updated_at으로 정렬할 수 있습니다.
  • tags: 태그 리스트를 사용합니다.

FastAPI는 쿼리 매개변수를 추출해 Pydantic 모델의 필드로 매핑합니다.

1.2 문서에서 확인

  • /docs에서 API 문서 UI를 확인할 수 있으며, 모델로 정의된 쿼리 매개변수들이 자동으로 문서화됩니다.

2. 추가 쿼리 매개변수 허용하지 않기 (Forbid Extra Query Parameters)

특정 경우에는 쿼리 매개변수에 대해 추가적인 매개변수를 허용하지 않도록 제한할 수 있습니다. 이를 위해 Pydanticmodel_config 설정을 사용합니다.

2.1 추가 매개변수 제한

from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field

app = FastAPI()

class FilterParams(BaseModel):
    model_config = {"extra": "forbid"}

    limit: int = Field(100, gt=0, le=100)
    offset: int = Field(0, ge=0)
    order_by: Literal["created_at", "updated_at"] = "created_at"
    tags: list[str] = []

@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
    return filter_query
  • model_config = {"extra": "forbid"}: 정의되지 않은 추가 쿼리 매개변수를 받지 않도록 설정합니다.

2.2 잘못된 쿼리 매개변수를 보낸 경우

클라이언트가 정의되지 않은 매개변수를 보내면 오류 응답을 받게 됩니다.

  • 예시:
    • https://example.com/items/?limit=10&tool=plumbus
    • 응답:
    {
        "detail": [
            {
                "type": "extra_forbidden",
                "loc": ["query", "tool"],
                "msg": "Extra inputs are not permitted",
                "input": "plumbus"
            }
        ]
    }

3. 요약

  • Pydantic 모델을 사용하여 여러 쿼리 매개변수를 그룹으로 선언할 수 있으며, 이를 통해 검증과 메타데이터를 한 번에 처리할 수 있습니다.
  • model_config를 사용하여 추가적인 쿼리 매개변수를 허용하지 않도록 설정할 수 있습니다.
  • 이러한 기능을 사용하면 API의 유지 관리가 쉬워지고, 코드가 더욱 간결해집니다. 😎
profile
AI Engineer / 의료인공지능

0개의 댓글