Fast API 에서는 Flask에서 하던 것과 같이 Path Parameter를 설정할 수 있다.
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
위와 같이 선언을 하고 난 뒤, http://127.0.0.1:8000/items/item1 으로 url을 입력해보면 {"item_id":"item1"}
과 같은 결과를 얻을 수 있다.
Fast API의 장점인 Type Hinting을 사용하여 위의 코드를 바꿔보자
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
자료형으로 Parsing이 되며, 아까와 같이 item1이라는 값을 넘기면 error log를 보여준다.
{
"detail":[
{
"loc":[
"path",
"item_id"
],
"msg":"value is not a valid integer",
"type":"type_error.integer"
}
]
}
http://127.0.0.1:8000/items/1 로 url를 다시 요청을 보내면 {"item_id":1}
과 같은 결과를 return 한다.
path를 정의할 때, 순서가 중요하다.
만약 /users/me
요청을 보낸다고 가정해보자. 그런데 /users/{user_id}
의 path또한 있을 때, 정의된 순서에 따라 return 되는 결과 값이 달라진다.
@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}
위와 같은 순서로 정의가 되어있다면, read_user_me
를 먼저 마주치기에 {"user_id": "the current user"}
의 결과가 return된다.
만약 read_user
path가 먼저 위에 정의가 되어있었다면, {"user_id": "me"}
의 결과가 return 된다.
path parameter로 들어오는 값이 정해진 범위 내에 있을 때, **Enum
모듈**을 사용하여 해당 값들을 처리할 수 있다.
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@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"}
Enum
클래스와 str
클래스를 상속받은 ModelName
클래스를 정의했다. str
클래스를 상속받아서 내부 클래스 변수들은 string
형식이여야 한다는 것을 명시했다.
docs에서 보면 가능한 값들이 이미 정의되어 있기 때문에 아래와 같이 select box 형태로 정해진 값만 넣을 수 있도록 설계된다.
get_model
함수의 parameter로 model_name
이 들어오는데 이 파라미터의 자료형은 위에서 정의한 ModelName
이다. 이 말은 model/model_name
에서 넘어온 값이 ModelName
객체로 자동 Parsing이 된다는 것이다. model_name
을 출력해보면 Model.alexnet(resnet/lenet)
과 같이 출력이 된다.
또한, ModelName
은 Enum
객체이기 때문에, model_name.value == "lenet"
과 같이 ModelName.value
로 직접 string 값을 얻을 수 있다.
만약 ModelName
에 정의되지 않은 값이 들어왔을 경우, error를 return한다.
{
"detail":[
{
"loc":[
"path",
"model_name"
],
"msg":"value is not a valid enumeration member; permitted: 'alexnet', 'resnet', 'lenet'",
"type":"type_error.enum",
"ctx":{
"enum_values":[
"alexnet",
"resnet",
"lenet"
]
}
}
]
}
정상적인 값이 들어왔을 경우, model_name
이 ModelName
객체로 반환이 되고, return이 되면서 model_name
은 다시 JSON Parsing
이 가능한 String
객체로 변환이 된다.
{
"model_name": "alexnet",
"message": "Deep Learning FTW!"
}
파일을 원할 때, 파일 경로를 path parameter로 넘겨주어야할 때가 있다.
만약 API path가 /files/{file_path}
이고 file_path가 home/johndoe/myfile.txt
라고 해보자.
그렇게 되면 Full path는 /files/home/johndoe/myfile.txt
이 된다.
원래 OpenAPI에서는 path parameter 안에 path가 들어가는 것은 지원하지 않았다고 한다. 하지만 Fast API는 Starlette
덕분에 이 기능이 가능하다.
해당 기능을 사용하려면 path를 아래와 같이 정의해야된다.
/files/{file_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}
file_path가 슬래쉬를 포함해도 앞에 슬래쉬를 써줘야한다. 이 경우 전체 URL은
/files//home/johndoe/myfile.txt
이 될 것이다.
FastAPI를 사용하면 짧고 직관적인 표준 Python 유형 선언을 사용하여 다음과 같은 이점을 얻을 수 있다.