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
url_for(...)
reverse(...)
So, how can I obtain/build the URLs of hello_world
and hello_world_number
in a similar way?
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.
While an open-source framework, FastAPI is fully production-ready, with excellent documentation, support, and an easy-to-use interface.
We have got Router.url_path_for(...)
method which is located inside the starlette package
FastAPI
instanceThis 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/"
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
Request
instanceThis 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/"
}
request
parameter in every (or required) view to resolve the URL, which might raise an ugly feel to developers.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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With