공식문서 앞페이지에서는 validation을 하는데 아래 코드와 같이 만들어주었다.
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
from typing import Union
from fastapi import FastAPI, Query
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
Query를 default값을 넣는 위치에 대신 넣어주고, 내부에서 default인자에 None으로 똑같이 지정해주고, max_length와 같이 세부적인 validation을 설정할 수 있다.
여기서 max_length 는 최대 길이를 50자로 한정하는 옵션이다.
max_length 이외에 min_length, regular expression(정규표현식)을 사용할 수 있다.
정규표현식의 몇가지 예시는 아래와 같다.
- ^
: starts with the following characters, doesn't have characters before.
- fixedquery
: has the exact value fixedquery
.
- $
: ends there, doesn't have any more characters after fixedquery
.
위에서 우리는
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
함수를 통해서 추가적인 validation을 진행해 보았다.
하지만 위의 코드에서는 타입힌트와 검증규칙을 동시에 제고항게 되고 이는 문제가 발생할 수 있다 .물론
이전에 작성한 코드는 실제로 정상적으로 돌아가기는 한다.
하지만 Gpt4.0 에 질문을 한 결과 아래와 같은 이유로 Annotated 사용을 권장한다. 내용은 다음과같다.
그렇다면 Annotated를 활용한 코드를 살펴보자
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Annotated를 감싸주고 ,
를 기준으로 앞에는 타입힌트를 뒤에는 validation을 설정해주는 모습이다.
다른 코드들과 마찬가지로 기본값은 None을 받고 있음을 볼 수 있다.
Annotated
사용하기from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
...
을 사용함으로서 반드시 값을 넣어야 함을 전달해 줄 수있습니다.
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = ...):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
위와 같은 코드가 있을때 해석을 하면 query 파라미터로 문자열이 올수있고, 최소길이는 3글자이며, 반드시
값이 필요함을 뜻합니다.
만약에 해당 코드를 작성하고, get을 날릴때(조회를 할때) query파라미터를 작성하지 않는다면 응답결과를 받지못합니다.
만약에 ...
을 사용하는것이 익숙하지 않고, 원하지 않는다면 아래의 방식으로도 가능합니다.
Required
instead of Ellipsis(...)from fastapi import FastAPI, Query
from pydantic import Required
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = Required):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
...
대신에 Pydantic에서 Required를 가져와서 대신할 수 있습니다.
Query를 사용하여 쿼리 매개변수를 명시적으로 정의를 할 때 이를 선언하여 list로 받거나 다른 방식으로 여러값을 받도록 선언할 수 있다.
from typing import List, Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[List[str], None], Query()] = None):
query_items = {"q": q}
return query_items
The, With a URL like:
http://localhost:8000/items/?q=너무&q=쉽군&q=이정도야&q=껌이지
결과는 아래와 같이 나타나게 된다.
너무 길어서 다음 포스팅에 이어서 작성하겠습니다~