In official docs of FastAPI about templating using Jinja2, it shows a way to inject request
object and use predefined TemplateResponse
class to render Jinja2 template to HTML Response.
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/items/{id}", response_class=HTMLResponse)
async def read_item(request: Request, id: str):
return templates.TemplateResponse("item.html", {"request": request, "id": id})
This is good way, but it lacks flexibility and better declaration (you see we have to inject request to any endpoint using Jinja). So this is my way ;)
In deps.py
file
import typing
from jinja2 import Environment, contextfunction
from jinja2.loaders import PackageLoader
from fastapi import Request, Depends
''' Get Jinja2 dependency function, you can define more functions, filters or global vars here '''
def get_jinja2():
@contextfunction
def url_for(context: dict, name: str, **path_params: typing.Any) -> str:
request = context["request"]
return request.url_for(name, **path_params)
env = Environment(loader=PackageLoader("yourpackage"), autoescape=True)
env.globals["url_for"] = url_for
return env
''' Get view render function using Jinja2 environment injected above '''
def get_view(tpl : str):
def func_view(request: Request, env : Environment = Depends(get_jinja2)):
template = env.get_template(tpl)
def render(*args, **kwargs):
return template.render(request=request, *args, **kwargs)
return render
return func_view
Now, we use these dependency function in router function
from starlette.responses import HTMLResponse
from fastapi import FastAPI Depends
from yourpackage.deps import get_view
app = FastAPI()
''' We inject render function directly into router function with declared template file name, it makes more senses ! '''
@app.get('/hello/{name}', response_class=HTMLResponse)
def hello(name : str, render = Depends(get_view('hello.html')))
return render({"name": name})
In templates/hello.html
file
<h1>Hello !</h1>
Try open http://localhost:8000/hello/world
, then we get
<h1>Hello World !</h1>
ENJOY ! ;)