FastAPI: Render HTML Templates with Dynamic Content

Updated: May 16, 2023 By: Goodman Post a comment

Overview

FastAPI is often used to develop backend APIs. However, you can also use this web framework to render HTML templates and create websites with the help of the HTMLResponse class (can be imported from fastapi.responses) and the Jinja2Templates class (can be imported from fastapi.templating). You can see a live demo in the URL below:

https://api.slingacademy.com/v1/examples/sample-page.html

What you can do is not limited to static HTML files; it’s possible to pass Python variables to your HTML templates to display dynamic content. Let’s explore this in more great detail in this concise and practical article.

The Steps

A template can be a normal HTML file or can be created easily by mixing the standard HTML syntax with Jinja2 syntax like this:

<h1>Hi there</h1>
<p>{{ my_variable }}!</p>

The {{ my_variable }} part is a placeholder for the variable value. When the template is rendered, it will replace it with the actual value of my_variable. The recommended file extension for a template is .html.

In most cases, the process of connecting FastAPI and your HTML templates is:

1. Add a new directory named templates to the root of your project (you can choose another name if you like). This is where you store your HTML templates.

2. Install the jinja2 package:

pip install jinja2

3. Import Jinja2Templates from fastapi.templating:

from fastapi.templating import Jinja2Templates

4. Create a templates object that you can re-use later:

templates = Jinja2Templates(directory="templates")

5. Use the templates you created to render and return a TemplateResponse, passing the request as one of the key-value pairs in the Jinja2 “context”:

@app.get("/some-route", response_class=HTMLResponse)
async def some_route(request: Request):
    my_variable = "Welcome to Sling Academy"
    return templates.TemplateResponse("some-file.html", 
          {
              "request": request, 
               // pass your variables to HTML template here
              "my_variable": my_variable
          }
)

Note that you can pass more variables if you want.

Complete Example

In this example, we will use an HTML template to display a message and the current date time (passed from the Python code).

Screenshot:

Project file structure:

├── main.py
└── templates
    └── home.html

Install jinja2:

pip install jinja2

Add the following to main.py:

# slingacademy.com
# main.py

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

from datetime import datetime

app = FastAPI()

templates = Jinja2Templates(directory="templates")


@app.get("/", response_class=HTMLResponse)
async def home(request: Request):
    message = "Welcome to Sling Academy"

    # get and format current local date and time
    now = datetime.now() 
    current_time = now.strftime("%Y-%m-%d %H:%M:%S") 

    return templates.TemplateResponse(
        "home.html",
        {
            "request": request,
            "message": message,
            "current_time": current_time
        }
)

Then add this to templates/home.html:

<!-- templates/home.html -->
<html>

<head>
    <title>Home Page - Sling Academy</title>
</head>

<body style="padding: 30px">
    <!-- Display variables passed from Python code -->
    <h1>{{ message }}</h1>
    <h3>The current time is: {{ current_time }}</h3>
</body>

</html>

Start your app by running uvicorn main:app --reload then go to http://localhost:8000/ to check the result.