YouTip LogoYouTip

Fastapi Blog Jinja2 Templates

Jinja2 Templates

In this chapter, you will learn how to configure the Jinja2 template engine in FastAPI and build complete HTML pages using static files and template inheritance.


Two Rendering Modes in FastAPI

By default, FastAPI returns JSON (suitable for APIs), but it can also return HTML (suitable for SSR).

Both modes can coexist β€” the same project can provide JSON APIs and render web pages simultaneously.


Mounting Static Files

Static files (CSS, JS, images) are mounted to a specified path using StaticFiles.

Example

# File path: main.py

from fastapi import FastAPI

from fastapi.staticfiles import StaticFiles

app = FastAPI()

# Mount the "static/" directory to the "/static" path

# Accessing /static/css/style.css β†’ actually reads static/css/style.css

app.mount("/static", StaticFiles(directory="static"), name="static")

Referencing static files in templates:

Example

<link rel="stylesheet" href="/static/css/style.css">

<img src="/static/images/logo.png">

Configuring Jinja2 Templates

Example

# File path: main.py

from fastapi import FastAPI, Request

from fastapi.staticfiles import StaticFiles

from fastapi.templating import Jinja2Templates

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")

# Specify the templates directory

templates = Jinja2Templates(directory="templates")

@app.get("/")

def index(request: Request): # Note: Template routes must receive a Request parameter

    """Blog homepage"""

    return templates.TemplateResponse(

        "index.html",  # Template filename

        {# context data #}

        {

            "request": request,  # request must be passed (required by Jinja2Templates)

            "title": "TUTORIAL Blog"

        }

    )

FastAPI’s template rendering differs from Flask in two key ways: 1) The view function must accept the request: Request parameter; 2) request must be passed to the template as context. If request is omitted, the url_for() functionality in templates will fail.


Creating the base.html Parent Template

Example

<!-- File path: templates/base.html -->

<!DOCTYPE html>

<html lang="zh-CN">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>{% block title %}TUTORIAL Blog{% endblock %}</title>

    <link rel="stylesheet" href="/static/css/style.css">

    {% block extra_head %}{% endblock %}

</head>

<body>

    <header class="navbar">

        <a href="/" class="logo">TUTORIAL Blog (FastAPI)</a>

        <nav>

            <a href="/">Home</a>

            <a href="#">About</a>

        </nav>

    </header>

    <main class="container">

        {% block content %}{% endblock %}

    </main>

    <footer class="footer">

        <p>Β© 2024 TUTORIAL Blog. Powered by FastAPI.</p>

    </footer>

</body>

</html>

Creating the index.html Child Template

Example

<!-- File path: templates/index.html -->

{% extends 'base.html' %}

{% block title %}{{ title }}{% endblock %}

{% block content %}

    <h2 class="section-title">Latest Articles</h2>

    <p>Article list will be shown in later chapters.</p>

{% endblock %}

Using url_for() in FastAPI Templates

Similar to Flask, FastAPI supports url_for(), but routes must be explicitly named first.

Example

@app.get("/post/{post_id}", name="post_detail")  # name= assigns a name to the route

def post_detail(request: Request, post_id: int):

    return templates.TemplateResponse("post_detail.html",

                                      {"request": request, ...})

Example

<!-- Reference in template -->

<a href="{{ url_for('post_detail', post_id=3) }}">Article 3</a>

Creating Basic CSS Styles

Example

/* File path: static/css/style.css */

* { margin: 0; padding: 0; box-sizing: border-box; }

body {

    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

    background: #f5f5f5;

    color: #333;

}

.navbar {

    display: flex;

    justify-content: space-between;

    align-items: center;

    padding: 16px 40px;

    background: #fff;

    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);

}

.navbar .logo {

    font-size: 22px;

    font-weight: bold;

    color: #009688;

    text-decoration: none;

}

.navbar nav a {

    margin-left: 20px;

    text-decoration: none;

    color: #333;

}

.container {

    max-width: 960px;

    margin: 40px auto;

    padding: 0 20px;

}

.footer {

    text-align: center;

    padding: 20px;

    color: #999;

    border-top: 1px solid #eee;

}

.section-title {

    font-size: 24px;

    margin-bottom: 20px;

}

Chapter Summary

In this chapter, you learned how to configure frontend rendering in FastAPI: mounting static resources with StaticFiles, configuring template directories with Jinja2Templates, returning HTML with TemplateResponse, and the key differences from Flask in template rendering (the Request parameter must be passed).

← Fastapi Blog Pydantic SchemaFlask Blog Deploy β†’