Как разделить маршрутизатор по типу данных в параметре Path. (Дополнительный совет для конечной точки FastAPI.)

Как известно, FastAPI — это почти фреймворк, сделанный из Pydantic и Starlette. Итак, если они что-то обеспечивают, FastAPI тоже. И есть часть, которой нет в документе FastAPI, а только в Starlette. Один из них — это часть конечной точки, разделенная DataType Pathd.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item_by_id(
    item_id: int,
):
    return {"item_id": item_id}


@app.get("/items/{item_name}")
async def read_item_by_name(
    item_name: str,
):
    return {"item_name": item_name}

Войти в полноэкранный режим

Выйти из полноэкранного режима

Есть такой настроенный роутер.

Когда вы просматриваете автоматически созданный документ,

Описание изображения

Похоже на это. Если вы вставите в {item_id}указанный выше маршрутизатор будет работать, и если вы поместите строку в {item_name}будет работать указанный ниже маршрутизатор.

Описание изображения

Он работает, когда вы вводите тип int, но

Описание изображения

Но это создает проблему, когда вы вводите строку в item_name. Как вы можете видеть в сообщении об ошибке, говорится, что произошла ошибка, потому что значение, введенное в item_id, не было целым числом, но видно, что конечная точка, указанная пользователем, не работает.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item_by_id(
    item_id: int = Path(0, description="The ID of the item to get"),
):
    return {"item_id": item_id}


@app.get("/items/{item_name}")
async def read_item_by_name(
    item_name: str = Path("", description="The name of the item to get"),
):
    return {"item_name": item_name}

Войти в полноэкранный режим

Выйти из полноэкранного режима

Даже если вы инициализируете данные по умолчанию параметром типа пути, предоставленным FastAPI,

Описание изображения

Внутри видно, что вышеуказанная функция (read_item_by_id), который все еще получает item_id, выполняется.

Как вы можете догадаться, при запуске приложения FastAPI конечные точки сортируются внутри, а функции выше имеют более высокий приоритет, поэтому, если вы пишете несколько функций для одной и той же конечной точки, выполняется функция наверху. Вы также можете проверить это просто

from fastapi import FastAPI

app = FastAPI()


@app.get("/hello")
async def hello1(
):
    return {"hello": "world1"}


@app.get("/hello")
async def hello2(
):
    return {"hello": "world2"}

Войти в полноэкранный режим

Выйти из полноэкранного режима

Если вы настраиваете две конечные точки с одинаковым именем,

Описание изображения

Имя функции выглядит как Hello2, и это похоже на то, что функция, которую вы объявили позже, имеет приоритет

Описание изображения

Если вы действительно выполните его, вы увидите, что функция hello1, объявленная выше, была выполнена.

Теперь, когда мы знаем причину, как нам решить эту проблему? Это просто.
В части, где маршрут указывает параметр пути, вы можете указать тип данных.

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id:int}")
async def read_item_by_id(
    item_id: int,
):
    print("worked with item_id")
    return {"item_id": item_id}


@app.get("/items/{item_name:str}")
async def read_item_by_name(
    item_name: str,
):
    print("worked with item_name")
    return {"item_name": item_name}

Войти в полноэкранный режим

Выйти из полноэкранного режима

Как это. Запустив настроенный таким образом маршрутизатор, вы увидите, что он работает так, как задумано.

Описание изображения

Описание изображения

Если вы вставите int, он будет работать как int router

Описание изображения

Описание изображения

Если вы вставляете строку, она работает как строка.

И такого способа работы с конечными точками нет в FastAPI Tutorial. Это у Старлетт. Вы можете проверить это, обратившись к этой части.

Итак, в конце концов, чтобы стать хорошим пользователем FastAPI, вам нужно знать Pydantic и Starlette, а также +@ SqlAlchemy.