3. Path Parameters
1. Path Parameters
- Python 문자열 형식에서 사용하는 것과 동일한 구문으로 path "매개변수" 또는 "변수"를 선언할 수 있다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
- path 매개변수
item_id
의 값은item_id
인수로, 이것은 함수에 전달된다.
- 따라서 위의 코드를 실행하고
http://127.0.0.1:8000/items/foo
로 이동하면 다음과 같은 response가 표시된다.
2. Path parameters with types
- 표준 Python 타입 어노테이션을 사용하여 함수에서 path 매개변수 타입을 선언할 수 있다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
- 위의 코드에서 볼 수 있듯이
item_id
는int
로 선언된다. - 이렇게 하면 타입 및 에러를 검사하기가 편해진다.
3. Data conversion
- 위의 코드를 실행하고
http://127.0.0.1:8000/items/3
로 이동하면 다음과 같은 response가 표시된다.
- 함수가 수신하고 리턴한 값은
str "3"
이 아니라int 3
이다. - 따라서 어노테이션을 통한 타입 선언으로, FastAPI의 자동 request "parsing"을 이용할 수 있다.
4. Data validation
- 하지만 위의 코드를 실행하고
http://127.0.0.1:8000/items/foo
로 이동하면 다음과 같은 HTTP 에러가 표시된다.
{
"detail": [
{
"loc": ["path", "item_id"],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
- 에러가 표시된 이유는 path 매개변수
item_id
에int
가 아닌"foo"
값이 있기 때문이다.
- 또한 다음과 같이
http://127.0.0.1:8000/items/4.2
로 이동하면 동일한 HTTP 에러가 표시된다.
{
"detail": [
{
"loc": ["path", "item_id"],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
- 위와 같이 Python 타입 선언을 통해 FastAPI는 데이터 유효성 검사를 제공한다.
- 에러에는 유효성 검사가 통과하지 못한 지점도 명확하게 명시되어 있다.
- 이는 API와 상호 작용하는 코드를 개발하고 디버깅하는 데 유용하다.
5. Documentation
- 다음과 같이
http://127.0.0.1:8000/docs
로 이동하면 자동 대화형 API 문서가 표시된다.
6. Pydantic
- 모든 데이터 유효성 검사는 Pydantic에 의해 내부적으로 수행된다.
str
,float
,bool
및 기타 여러 복합 데이터 타입과 같은 타입 선언을 사용할 수 있다.
7. Order matters
- path operation을 생성할 때, 고정 path가 있는 상황이 발생할 수 있다.
- 예를 들어,
/users/me
와 같은 고정 path를 사용하여 현재 사용자에 대한 데이터를 가져오면서/users/{user_id}
와 같은 path를 사용하여 일부 사용자 ID로 특정 사용자에 대한 데이터를 가져올 수도 있다. - 이때 path operation은 순서대로 평가되므로
/users/{user_id}
에 대한 path보다/users/me
에 대한 path가 먼저 선언된 것을 확인해야만 한다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
- 이런 경우,
/users/{user_id}
에 대한 path는/users/me
에 대한 path와 일치하게 되어 값이"me"
인user_id
매개변수를 수신하게 된다.
8. Predefined values
- path 매개변수를 수신하는 path operation이 있지만, 사용 가능한 유효한 path 매개변수 값을 미리 정의하려는 경우 표준 Python
Enum
을 사용할 수 있다.
1) Create an Enum
class
Enum
을 임포트한 후str
및Enum
에서 상속하는 하위 클래스를 만든다.str
에서 상속함으로써 API 문서는 값이String
타입이어야 올바르게 렌더링할 수 있다는 것을 알 수 있다.- 그런 다음 사용 가능한 유효한 값이 될 고정 값으로 클래스 속성을 만든다.
from enum import Enum
from fastapi import FastAPI
app = FastAPI()
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
2) Declare a path parameter
- 그런 다음
ModelName
이라는 enum 클래스를 타입 어노테이션으로 사용하여 path parameter를 생성한다.
from enum import Enum
from fastapi import FastAPI
app = FastAPI()
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
3) Check the docs
- path 매개변수에 사용 가능한 값이 미리 정의되어 있기 때문에 대화형 문서는 이를 보기 좋게 표시할 수 있다.
4) Working with Python enumerations
- path 매개변수의 값은 열거형 멤버가 된다.
(1) Compare enumeration members
- 생성한 enum
ModelName
의 열거형 멤버를 비교할 수 있다.
from enum import Enum
from fastapi import FastAPI
app = FastAPI()
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
(2) Get the enumeration value
model_name.value
를 사용하여 실제 값을 얻을 수 있다.
from enum import Enum
from fastapi import FastAPI
app = FastAPI()
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
(3) Return enumeration members
- JSON body에 중첩된 경우에도 path operation에서 enum 멤버를 반환할 수 있다.
- 클라이언트에 반환하기 전에 해당 값으로 변환된다.
from enum import Enum
from fastapi import FastAPI
app = FastAPI()
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
- 클라이언트에서는 다음과 같은 JSON response를 받게 된다.
9. Path parameters containing paths
- path가
/files/{file_path}
인 path operation이 있다고 가정해 보자. - 이런 상황에서
home/johndoe/myfile.txt
와 같은 path를 포함하려면file_path
자체가 필요하다. - 따라서 해당 파일의 URL은
/files/home/johndoe/myfile.txt
과 같게 된다.
1) Path convertor
- Starlette에서 직접 옵션을 사용하면, 다음과 같은 URL을 사용하여 path가 포함된 path 매개변수를 선언할 수 있다.
- 이 경우 매개변수의 이름은
file_path
이고 마지막 부분인:path
는 매개변수가 모든 path와 일치해야 함을 알려준다.
- 따라서 다음과 같이 사용할 수 있다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
Note
- 위의 예제와는 다르게, 선행 슬래시(
/
)가 있는 매개변수/home/johndoe/myfile.txt
가 필요한 경우가 발생할 수 있다. - 이런 경우 URL은 이중 슬래시(
//
)가 있는/files//home/johndoe/myfile.txt
와 같은 모양이 된다는 것을 유의해야 한다.