Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FastAPI: Retrieve URL from view name ( route name )

Suppose I have following views,

from fastapi import FastAPI

app = FastAPI()


@app.get('/hello/')
def hello_world():
    return {"msg": "Hello World"}


@app.get('/hello/{number}/')
def hello_world_number(number: int):
    return {"msg": "Hello World Number", "number": number}

I have been using these functions in Flask and Django

  • Flask: url_for(...)
  • Django: reverse(...)

So, how can I obtain/build the URLs of hello_world and hello_world_number in a similar way?

like image 372
JPG Avatar asked Sep 01 '20 07:09

JPG


People also ask

How do I find my client IP address on FastAPI?

Use the Request object directly Let's imagine you want to get the client's IP address/host inside of your path operation function. For that you need to access the request directly. By declaring a path operation function parameter with the type being the Request FastAPI will know to pass the Request in that parameter.

Is FastAPI production ready?

While an open-source framework, FastAPI is fully production-ready, with excellent documentation, support, and an easy-to-use interface.


2 Answers

We have got Router.url_path_for(...) method which is located inside the starlette package

Method-1: Using FastAPI instance

This method is useful when you are able to access the FastAPI instance in your current context. (Thanks to @Yagizcan Degirmenci)

from fastapi import FastAPI

app = FastAPI()


@app.get('/hello/')
def hello_world():
    return {"msg": "Hello World"}


@app.get('/hello/{number}/')
def hello_world_number(number: int):
    return {"msg": "Hello World Number", "number": number}


print(app.url_path_for('hello_world'))
print(app.url_path_for('hello_world_number', number=1))
print(app.url_path_for('hello_world_number', number=2))

# Results

"/hello/"
"/hello/1/"
"/hello/2/"

Drawback

  • If we are using APIRouter, router.url_path_for('hello_world') may not work since router isn't an instance of FastAPI class. That is, we must have the FastAPI instance to resolve the URL

Method-2: Request instance

This method is useful when you are able to access the Request instance (the incoming request), usually, within a view.

from fastapi import FastAPI, Request

app = FastAPI()


@app.get('/hello/')
def hello_world():
    return {"msg": "Hello World"}


@app.get('/hello/{number}/')
def hello_world_number(number: int):
    return {"msg": "Hello World Number", "number": number}


@app.get('/')
def named_url_reveres(request: Request):
    return {
        "URL for 'hello_world'": request.url_for("hello_world"),
        "URL for 'hello_world_number' with number '1'": request.url_for("hello_world_number", number=1),
        "URL for 'hello_world_number' with number '2''": request.url_for("hello_world_number", number=2})
    }

# Result Response

{
    "URL for 'hello_world'": "http://0.0.0.0:6022/hello/",
    "URL for 'hello_world_number' with number '1'": "http://0.0.0.0:6022/hello/1/",
    "URL for 'hello_world_number' with number '2''": "http://0.0.0.0:6022/hello/2/"
}

Drawback

  • We must include the request parameter in every (or required) view to resolve the URL, which might raise an ugly feel to developers.
like image 56
JPG Avatar answered Sep 22 '22 16:09

JPG


Actually you don't need to reinvent the wheel. FastAPI supports this out-of-box (Actually Starlette), and it works pretty well.

app = FastAPI()

@app.get("/hello/{number}/")
def hello_world_number(number: int):
    return {"msg": "Hello World Number", "number": number}

If you have an endpoint like this you can simply use

In:  app.url_path_for("hello_world_number", number=3)
In:  app.url_path_for("hello_world_number", number=50)

Out: /hello/3/
Out: /hello/50/

In FastAPI, APIRouter and FastAPI(APIRoute) inherits from Router(Starlette's) so, if you have an APIRouter like this, you can keep using this feature

router = APIRouter()

@router.get("/hello")
def hello_world():
    return {"msg": "Hello World"}

In:  router.url_path_for("hello_world")
Out: /hello
like image 21
Yagiz Degirmenci Avatar answered Sep 19 '22 16:09

Yagiz Degirmenci