본문 바로가기

웹 프레임워크/FastAPI

FastAPI - 02 (경로(Path) 매개변수)

출처: https://fastapi.tiangolo.com/tutorial/path-params/
아래의 내용은 공식 사이트의 내용을 제 경험과 생각을 추가하여 다시 정리한 것 입니다.

경로(Path) 매개변수 예시

아래는 경로(Path)가 포함되어 있는 url의 예시입니다.

http://127.0.0.1:8000/items/foo

itemsfoo가 경로입니다.

아래는 경로 매개변수를 사용하는 예시입니다.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")    # 경로 매개변수 - item_id
async def read_item(item_id):   # 함수 매개변수 - item_id
    return {"item_id": item_id}

경로 매개변수(item_id)가 함수 매개변수(item_id)로 전달 됩니다.

http://127.0.0.1:8000/items/foo

위의 url로 접속 하면 아래의 결과가 나옵니다.

{"item_id":"foo"}

fooitem_id에 매핑 됩니다.

경로 Parameters (Data Type)

경로 매개변수의 데이터 타입을 지정 할 수 있습니다.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: int):  # item_id는 int Type으로 변경 됨
    return {"item_id": item_id}

함수 매개 변수 item_id가 문자열로 타입이 변경 됩니다.

http://127.0.0.1:8000/items/3

위의 url로 접속 하면 아래의 결과가 나옵니다.

{"item_id":3}

아래와 같이 경우는 에러가 발생합니다.

http://127.0.0.1:8000/items/foo
# 또는  
http://127.0.0.1:8000/items/3.4

경로 매개변수(item_id)가 int Type이 아닌 foo, 3.4가 매핑 되어 에러 발생 합니다.

{
  "detail": [
    {
      "type": "int_parsing",
      "loc": [
        "path",
        "item_id"
      ],
      "msg": "Input should be a valid integer, unable to parse string as an integer",
      "input": "foo",
      "url": "https://errors.pydantic.dev/2.1/v/int_parsing"
    }
  ]
}

함수 작성 순서

/user/me/user/{user_id} 2개의 경로가 있다고 가정 하겠습니다.
/user/me는 현재 로그인한 사용자의 정보를 반환 합니다.
/user/{user_id}는 user_id에 해당하는 사용자의 정보를 반환 합니다.
me라는 user_id가 있다고 가정 하겠습니다.
/user/me를 호출 하면 2개의 함수 중에 어떤 함수가 호출 될까요?

먼저 선언 된 함수가 호출 됩니다.

/user/me를 선언하고 두 번째로 /user/{user_id}를 선언 한 경우

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}
{"user_id":"the current user"}

/user/{user_id}를 선언하고 두 번째로 /user/me를 선언 한 경우

from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}")        # 먼저 선언 됨
async def read_user(user_id: str):
    return {"user_id": user_id}     # 반환


@app.get("/users/me")
async def read_user_me():
    return {"user_id": "the current user"}
{"user_id":"me"}

경로 매개변수의 사전 선언

사전에 경로 매개변수 값을 정의 할 수 있습니다.

Enum Class 사용합니다.

from enum import Enum       # enum 모듈 임포트

from fastapi import FastAPI


class ModelName(str, Enum): # enum Class 선언, 열거형의 항목은 문자열 타입
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


app = FastAPI()


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):     # 함수 매개 변수(model_name)는 ModelName Type
    if model_name is ModelName.alexnet:     # is 연산자를 사용하여 비교
        return {"model_name": model_name, "message": "Deep Learning FTW!"}

    if model_name.value == "lenet":         # value 속성을 사용하여 비교
        return {"model_name": model_name, "message": "LeCNN all the images"}

    return {"model_name": model_name, "message": "Have some residuals"} # 나머지

앞에서 경로 매개변수(->함수 매개변수)의 패턴과 같습니다.
item_id: int -> int 타입의 item_id변수
model_name: ModelName -> ModelName 타입의 model_name 변수

http://127.0.0.1:8000/models/alexnet  
# 또는  
http://127.0.0.1:8000/models/resnet  
# 또는  
http://127.0.0.1:8000/models/lenet  

위의 url로 접속 하면 아래의 결과가 나옵니다.

// alexnet
{"model_name":"alexnet","message":"Deep Learning FTW!"}
// resnet
{"model_name":"resnet","message":"Have some residuals"}
// lenet
{"model_name":"lenet","message":"LeCNN all the images"}

만약 아래와 같이 열거형(ModelName)에 없는 값으로 호출 하면

http://127.0.0.1:8000/models/vggnet

아래와 같은 오류가 발생 됩니다.

{
  "detail": [
    {
      "type": "type_error.enum",
      "loc": [
        "path",
        "model_name"
      ],
      "msg": "value is not a valid enumeration member; permitted: 'alexnet', 'resnet', 'lenet'",
      "ctx": {
        "enum_values": [
          "alexnet",
          "resnet",
          "lenet"
        ]
      },
      "param": "alexnet",
      "url": "https://errors.pydantic.dev/1.7.3/"
    }
  ]
}

경로 변환기

url: files/home/johndoe/myfile.txt
위의 url 같이 경로를 포함하는 경로 매개변수를 선언 할 수 있습니다.

from fastapi import FastAPI

app = FastAPI()


@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
    return {"file_path": file_path}
http://127.0.0.1:8000/files/home/johndoe/myfile.txt

위의 url로 접속 하면 아래의 결과가 나옵니다.

{"file_path":"home/johndoe/myfile.txt"}