Plantilla Jinja2

En este capítulo aprenderás a configurar el motor de plantillas Jinja2 en FastAPI, y a construir páginas HTML completas con archivos estáticos y herencia de plantillas.


Dos modos de renderizado de FastAPI

FastAPI devuelve JSON por defecto (adecuado para API), pero también puede devolver HTML (adecuado para SSR).

Los dos modos pueden coexistir: el mismo proyecto puede ofrecer una API JSON y también renderizar páginas web.


Montar archivos estáticos

Los archivos estáticos (CSS, JS, imágenes)StaticFilesse montan en la ruta especificada.

Ejemplo

# Ruta del archivo: main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

# Montar el directorio static/ en la ruta /static
# Acceder a /static/css/style.css → en realidad lee static/css/style.css
app.mount("/static", StaticFiles(directory="static"), name="static")

Referenciar archivos estáticos en la plantilla:

Ejemplo

<link rel="stylesheet" href="/static/css/style.css">
<img src="/static/images/logo.png">

Configurar la plantilla Jinja2

Ejemplo

# Ruta del archivo: 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")

# Especificar el directorio de plantillas
templates = Jinja2Templates(directory="templates")

@app.get("/")
def index(request: Request):       # Nota: la ruta de la plantilla debe recibir el parámetro Request
    """Página de inicio del blog"""
    return templates.TemplateResponse(
        "index.html",              # Nombre del archivo de plantilla
        {                          # Datos de context
            "request": request,    # request debe pasarse (requisito de Jinja2Templates)
            "title": "Blog de EJEMPLO"
        }
    )

La renderización de plantillas en FastAPI tiene dos diferencias clave con Flask: 1. La función de vista debe recibirrequest: Requestel parámetro; 2.requestdebe pasarse a la plantilla como context. Si se omite request, la función url_for de la plantilla dejará de funcionar.


Crear la plantilla padre base.html

Ejemplo

<!-- Ruta del archivo: 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 %}Blog de EJEMPLO{% endblock %}</title>
    <link rel="stylesheet" href="/static/css/style.css">
    {% block extra_head %}{% endblock %}
</head>
<body>
    <header class="navbar">
        <a href="/" class="logo">Blog de EJEMPLO (FastAPI)</a>
        <nav>
            <a href="/">Inicio</a>
            <a href="#">Acerca de</a>
        </nav>
    </header>

    <main class="container">
        {% block content %}{% endblock %}
    </main>

    <footer class="footer">
        <p>© 2024 Blog de EJEMPLO. Desarrollado con FastAPI.</p>
    </footer>
</body>
</html>

Crear la plantilla hija index.html

Ejemplo

<!-- Ruta del archivo: templates/index.html -->
{% extends 'base.html' %}

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

{% block content %}
<h2 class="section-title">Últimos artículos</h2>
<p>La lista de artículos se mostrará en capítulos posteriores.</p>
{% endblock %}

url_for() en plantillas de FastAPI

Al igual que Flask, FastAPI también admiteurl_for(), pero primero es necesario nombrar la ruta.

Ejemplo

@app.get("/post/{post_id}", name="post_detail")   # name= asigna un nombre a la ruta
def post_detail(request: Request, post_id: int):
    return templates.TemplateResponse("post_detail.html",
        {"request": request, ...})

Ejemplo

<!-- Referencia en la plantilla -->
<a href="{{ url_for('post_detail', post_id=3) }}">Artículo 3</a>

Crear estilos CSS básicos

Ejemplo

/* Ruta del archivo: 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; }

Resumen del capítulo

En este capítulo has aprendido la configuración de renderizado frontend en FastAPI: StaticFiles para montar recursos estáticos, Jinja2Templates para configurar el directorio de plantillas, TemplateResponse para devolver HTML, y las diferencias clave con Flask en el renderizado de plantillas (el parámetro Request debe pasarse).

Otras extensiones