https://fastapi.tiangolo.com/ko/tutorial/query-params-str-validations/
Query Parameters and String Validations - FastAPI
In Python 3.9 or above, Annotated is part of the standard library, so you can import it from typing. from typing import Annotated from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") async def read_items(q: Annotated[str | None, Query(max
fastapi.tiangolo.com
<FastAPI 공식문서 참조>
1. Query Parameters and String Validations
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
쿼리 변수 q는 str자료형이 될 수 도있고 None(없을) 수 도 있다. 이때 default는 None으로 명시해놨다.
2. Additional validation
str 자료형 q가 제공되었을 때, q의 길이는 50을 넘게 실행되지 않는다. 이를 사용할 수 있게 강화(enforce)해 보자.
2-1. Import Query and Annotated
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
* 파이썬 3.9이상에서는 Annotated는 표준 라이브러리의 일부분이라 typing에서 import할 수 있다.
3.9 아래에서는 typing_extensions 에서 import해야 한다.
Annotated 라이브러리는 내 파라미터에 메타데이터(데이터를 설명하는 데이터)를 삽입할 수 있다.
q: Annotated[ str | None ] = None
최상단 코드의 q 선언문을 Annotated로 감싼 형태이다.
현재 상태는 최상단 코드의 q 선언문과 같은 의미를 가진다.
2-2. Add Query to Annotated in the q parameter
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
q 매개변수에 쿼리의 최대 길이가 50이라는 설정을 넣었다.
FastAPI는 이 값을 쿼리 파라미터에서 추출할 수 있다. 우리는 Annotated를 통해 Additional Validation을 추가할 수 있다.
*data가 위 조건에 유효하지 않다면 명확한 오류를 볼 수 있다.
*또한 docs UI에도 위 조건이 보일 것이다.
2-3. Alternative (old) Query as the default value
async def read_items(q: str | None = Query(default=None, max_length=50)):
쿼리의 기본값을 선언하는 구버전의 방식이다.(before 0.95.0)
2-4. Query as the default value or in Annotated
Annotated 속 Query 는 default parameter를 작성할 수 없다.
대신 함수 파라미터의 실제 default value를 사용해야 한다. 그렇지 않으면 일관성이 없게 된다.
예를 들어, 아래 Query는 허용되지 않는다.
q: Annotated[str Query(default="rick")] = "morty"
왜냐하면, default value가 "rick" 인지 "morty"인지 명확하지 않기 때문이다.
그래서 다음과 같이 작성해야 한다.
q: Annotated[str, Query()] = "rick"
혹은 구 버전에선,
q: str = Query(default="rick")
이렇게 적어야 한다.
2-4. Advantages of Annotated
함수 파라미터의 default value보다 Annotated를 사용하는 것이 권장된다.
왜냐하면,
- 함수 파라미터의 default value(기본값)는 actual default value라서, 일반적으로 파이썬에서 더 직관적이다.
- FastAPI외부에서 같은 함수를 불러온다면, 예상대로 작동할텐데, 만약 기본값이 없는 required parameter가 들어오면 내 편집기는 에러를 발생시킬 것이기 때문이다. 파이썬도 마찬가지다.
- Annotated없이 구 버전 스타일로 짜게 되면 작동은 잘 될지라도 값이 내 예상과 달라질 수 있다.
2-5. Add more vaildations
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(min_length=3, max_length=50)] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
min_length도 추가 가능하다.
2-6. Add regular expressions
@app.get("/items/")
async def read_items(
q: Annotated[
str | None, Query(min_length=3, max_length=50, regex="^fixedquery$")
] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
정규표현식도 추가 가능하다.
- ^ : starts with the following characters
- $ : ends there, doesn't have any more characters after fixedquery.
정규 표현식은 모든 사람들에게 어려운 주제니까 어렵다고 낙담하지 않아도 된다.
그런데 언젠간 FastAPI에서 쓰고 있는 자신을 발견할 것이다.
2-7. Default values
async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
q가 "fixedquery"라는 Default value를 가지게 코드를 짤 수 있다.
2-8. Make it Required
기본값을 선언하지 않으면 required parameter가 된다(선택적이지 않고 무조건 인자로 값이 들어와야 하는 매개변수).
2-8-1. Required with Ellipsis ( ... )
Ellipsis ( ... )를 통해 required parameter임을 명시해 줄 수 있다.
@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
... 과 None 키워드를 같이 써도 여전히 required parameter로 작동한다.
이때는 None을 인자로 삽입해 None의 의미를 가지게 하는 것 같다.
2-8-2. Use Pydantic's Required instead of Ellipsis ( ... )
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import Required
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
... 대신 Required(from pydantic)을 통해 필요 매개변수임을 명시할 수도 있다.
2-9. Query parameter list / multiple values
@app.get("/items/")
async def read_items(q: Annotated[Union[list[str], None], Query()] = None):
query_items = {"q": q}
return query_items
위처럼 쿼리 파라미터에 리스트 값을 넣어 다중 인자를 받게 할 수도 있다.
이때 URL은 아래처럼 작성해야 한다.
http://localhost:8000/items/?q=foo&q=bar
이때, URL을 향한 response는 다음과 같다.
{
"q": [
"foo",
"bar"
]
}
* 이렇게 list 타입으로 query parameter를 작성할 경우, Query를 뒤에 명시해줘야 한다.
그렇지 않으면 request body로 해석될 수도 있다,
list형태로 쓰면, swagger UI 내 에서 이렇게 다중 형태의 Desciprtion을 볼 수 있다.
2-9-1. Query parameter list / multiple values with defaults
@app.get("/items/")
async def read_items(q: Annotated[list[str], Query()] = ["foo", "bar"]):
query_items = {"q": q}
return query_items
이때 q의 defaults value는 ["foo", "bar"] 이 된다.
2-9-2. Using list directly
List[str] (or list[str] in Python 3.9+) 대신에, 그냥 list 라고 직접 쓸 수도 있다.
@app.get("/items/")
async def read_items(q: Annotated[list, Query()] = []):
query_items = {"q": q}
return query_items
그런데 이럴 때 list 내부 자료형에 대한 vaildation check는 이루어 지지 않는다.
3. Declare more metadata
parameter에 대한 정보를 삽입할 수 있다.
그 정보는 생성된 OpenAPI에 포함될 것이고, UI(User Interfaces) 와 exteranl tools(외부 도구) 문서에 사용될 것이다.
- title 삽입 가능
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(title="Query string", min_length=3)] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
- description 삽입 가능
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
4. Alias parameters
parameter의 별명(다른 이름)을 지정해 줄 수 있다
http://127.0.0.1:8000/items/?item-query=foobaritems
위를 보면.
한 쿼리가 item-query라는 이름을 가지는 데, 파이썬은 이러한 형태의 변수 이름을 지원하지 않기 때문에
item_query라고 가장 비슷한 의미로 지을 수 있다.
그래도 item-query라고 정확히 변수명을 짓고 싶다면
alias를 선언하자. 그럼 변수로 들어온 인자가 parameter value를 찾는데 사용될 것이다.
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(alias="item-query")] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
5. Deprecating parameters
(*더이상 사용하지 않는 매개변수)
내가 하나의 매개변수를 더이상 사용하고 싶지 않아도, 항상 이를 남겨놔야 한다.
이를 사용하는 클라이언트가 존재하기 때문이다. 이럴 때, docs에 이를 deprecated(which means something's state is false)상태로 명확히 보여줘야 한다.
그러면 매개변수 deprecated = True 를 Query 로 넘겨주면 된다.
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
regex="^fixedquery$",
deprecated=True, #더이상 사용하지 않음을 명시
),
] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
이러고 서버를 구동하면
docs는 다음과 같이 나타나게 된다.
6. Exclude from OpenAPI
생성된 OpenAPI 스키마에서 쿼리파라미터를 제외하고 싶다면(자동 문서화 시스템에서도),
Query의 include_in_schema 매개변수를 False 로 설정하면 된다.
@app.get("/items/")
async def read_items(
hidden_query: Annotated[str | None, Query(include_in_schema=False)] = None
):
if hidden_query:
return {"hidden_query": hidden_query}
else:
return {"hidden_query": "Not found"}
7. Recap(요약)
여러 파라미터들,
일반적 검증 및 메타데이터
- alias8.
- title
- description
- deprecated
strings를 구체적으로 검증
- min_length
- max_length
- regex
다음 챕터에서는 다른 타입의 검증을 어떻게 선언하는 지 배울 것이다.
8. Reference
https://fastapi.tiangolo.com/ko/tutorial/query-params-str-validations/
Query Parameters and String Validations - FastAPI
In Python 3.9 or above, Annotated is part of the standard library, so you can import it from typing. from typing import Annotated from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") async def read_items(q: Annotated[str | None, Query(max
fastapi.tiangolo.com
'프레임워크 > FastAPI' 카테고리의 다른 글
[FastAPI] FastAPI [6] Body - Multiple Parameters (0) | 2023.03.27 |
---|---|
[FastAPI] FastAPI [5] Path Parameters and Numeric Validations (0) | 2023.03.20 |
[FastAPI] FastAPI [3] - Request Body (0) | 2023.03.13 |
[FastAPI] FastAPI [2] Tutorial (1) | 2023.03.12 |
[FastAPI] FastAPI [1] - 공식 문서 정리 및 예제 실습 (0) | 2023.03.05 |