DEV Community

gyudoza
gyudoza

Posted on

How to Divide router by Datatype in Path parameter. (FastAPI endpoint Advanced tip.)

How to Divide router by Datatype in Path parameter. (FastAPI endpoint Advanced tip.)

As known as well, FastAPI is almost a framework made of Pydantic and Starlette. So, If these provide something, FastAPI does too. And there's a part that's not in the FastAPI document, but only in Starlette. One of them is the part of endpoint that devided by Pathd's DataType.

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}

Enter fullscreen mode Exit fullscreen mode

There is a router configured like this.

When you view an automatically created document,

Image description

It looks like this. If you put int in {item_id}, the router above will run, and if you put string in {item_name}, the router below will run.

Image description

It works when you input int type but,

Image description

But it makes a problem when you input string at item_name. As you can see at the error message, It is said that an error occurred because the value entered in item_id was not an integer, but it can be seen that the endpoint intended by the user is not operated.

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}

Enter fullscreen mode Exit fullscreen mode

Even if you initialize the default data with the Path type parameter provided by FastAPI,

Image description

Inside, it can be seen that the above function (read_item_by_id) that still receives the item_id is executed.

As you can guess, when the FastAPI app runs, the endpoints are sorted inside, and the functions above are higher in priority, so if you write multiple functions on the same endpoint, the function at the top is executed. You can test this simply, too

from fastapi import FastAPI

app = FastAPI()


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


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

Enter fullscreen mode Exit fullscreen mode

If you configure two endpoints with the same name,

Image description

The function name appears to be Hello2 and it's like a function that you declared later has priority

Image description

If you actually execute it, you will see that the 'hello1' function declared above has been executed.

Now that we know the cause, how do we solve this? It's simple.
In the part where route specifies the path parameter, you can specify the data_type.

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}

Enter fullscreen mode Exit fullscreen mode

Like this. When you run the router configured in this way, you can see that it works as intended.

Image description

Image description

If you insert an int, it works as an int router

Image description

Image description

If you insert a string, it works as a string.

And this way of working with endpoints is not in FastAPI Tutorial. It is in Starlette's. https://www.starlette.io/routing/ You can check it out by referring to this part.

So in the end, in order to make good user of FastAPI, you need to know Pydantic and Starlette, and +@ SqlAlchemy.

Top comments (1)

Collapse
 
veena_rao_028b4ba1a04bb06 profile image
Veena Rao

i dont see the pydantic validation happens in this case for negative value given