FastAPI: Templates

Descubre cómo usar templates en FastAPI con Jinja2 para crear páginas HTML dinámicas y mejorar tus aplicaciones web con datos del backend.

Aprende FastAPI GRATIS y certifícate

Templates en FastAPI

Los templates representan una funcionalidad fundamental para crear aplicaciones web dinámicas que combinan datos del servidor con presentación visual. En FastAPI, los templates permiten generar páginas HTML dinámicas utilizando datos procesados por el backend, creando una experiencia web completa e interactiva.

¿Qué son los templates?

Un template es un archivo que contiene la estructura base de una página web con marcadores especiales donde se insertan datos dinámicos. Estos marcadores actúan como espacios reservados que se reemplazan con información real cuando se procesa la solicitud.

FastAPI utiliza Jinja2 como motor de templates por defecto, una herramienta que permite crear plantillas HTML con sintaxis Python integrada. Esta integración facilita la inserción de variables, bucles y condicionales directamente en el HTML.

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

app = FastAPI()
templates = Jinja2Templates(directory="templates")

@app.get("/usuario/{nombre}", response_class=HTMLResponse)
async def mostrar_usuario(request: Request, nombre: str):
    return templates.TemplateResponse(
        "usuario.html", 
        {"request": request, "nombre": nombre}
    )

Configuración básica de templates

Para trabajar con templates en FastAPI, necesitas configurar el directorio donde se almacenan las plantillas y crear la instancia de Jinja2Templates. Esta configuración establece la base para renderizar contenido dinámico.

La estructura típica incluye una carpeta templates en el directorio raíz del proyecto, donde se organizan todos los archivos HTML:

proyecto/
├── main.py
├── templates/
│   ├── base.html
│   ├── inicio.html
│   └── usuario.html

El objeto Jinja2Templates actúa como intermediario entre FastAPI y el motor de templates, procesando las plantillas y sustituyendo los marcadores con datos reales:

from fastapi.templating import Jinja2Templates

# Configuración del directorio de templates
templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def pagina_inicio(request: Request):
    datos = {"titulo": "Mi Aplicación", "version": "1.0"}
    return templates.TemplateResponse(
        "inicio.html",
        {"request": request, **datos}
    )

Sintaxis básica de Jinja2

Jinja2 utiliza una sintaxis específica para integrar lógica Python dentro del HTML. Los elementos principales incluyen variables, expresiones y bloques de control que permiten crear contenido dinámico.

Variables y expresiones se insertan utilizando dobles llaves:

<!-- templates/usuario.html -->
<h1>Bienvenido, {{ nombre }}!</h1>
<p>Tu edad es: {{ edad }} años</p>
<p>Email: {{ email | upper }}</p>

Los filtros modifican el contenido de las variables antes de mostrarlas. Jinja2 incluye filtros integrados como upper, lower, length y muchos más:

<p>Nombre en mayúsculas: {{ nombre | upper }}</p>
<p>Longitud del nombre: {{ nombre | length }}</p>
<p>Fecha formateada: {{ fecha | strftime('%d/%m/%Y') }}</p>

Estructuras de control

Las estructuras de control en Jinja2 permiten implementar lógica condicional y bucles dentro de las plantillas, utilizando la sintaxis {% %} para delimitar bloques de código.

Condicionales para mostrar contenido según criterios específicos:

{% if usuario_autenticado %}
    <p>Bienvenido de vuelta, {{ nombre_usuario }}!</p>
    <a href="/logout">Cerrar sesión</a>
{% else %}
    <p>Por favor, inicia sesión</p>
    <a href="/login">Iniciar sesión</a>
{% endif %}

Bucles para iterar sobre listas y diccionarios:

<ul>
{% for producto in productos %}
    <li>
        <strong>{{ producto.nombre }}</strong> - 
        ${{ producto.precio }}
        {% if producto.disponible %}
            <span class="disponible">En stock</span>
        {% endif %}
    </li>
{% endfor %}
</ul>

Herencia de templates

La herencia de templates es una característica avanzada que permite crear una estructura base reutilizable. Esta funcionalidad reduce la duplicación de código y mantiene consistencia visual en toda la aplicación.

Template base que define la estructura común:

<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block titulo %}Mi Aplicación{% endblock %}</title>
    <link rel="stylesheet" href="/static/styles.css">
</head>
<body>
    <nav>
        <a href="/">Inicio</a>
        <a href="/productos">Productos</a>
    </nav>
    
    <main>
        {% block contenido %}{% endblock %}
    </main>
    
    <footer>
        <p>&copy; 2024 Mi Aplicación</p>
    </footer>
</body>
</html>

Template hijo que extiende la base:

<!-- templates/productos.html -->
{% extends "base.html" %}

{% block titulo %}Productos - Mi Aplicación{% endblock %}

{% block contenido %}
    <h1>Lista de Productos</h1>
    {% for producto in productos %}
        <div class="producto">
            <h3>{{ producto.nombre }}</h3>
            <p>Precio: ${{ producto.precio }}</p>
        </div>
    {% endfor %}
{% endblock %}

Integración con datos dinámicos

Los templates dinámicos cobran vida cuando se combinan con datos del backend. FastAPI facilita el paso de información desde las rutas hacia las plantillas mediante diccionarios de contexto.

from datetime import datetime
from typing import List

@app.get("/dashboard", response_class=HTMLResponse)
async def dashboard(request: Request):
    # Simulación de datos del backend
    estadisticas = {
        "usuarios_activos": 1250,
        "ventas_hoy": 45,
        "ingresos_mes": 15750.50
    }
    
    actividad_reciente = [
        {"usuario": "Ana García", "accion": "Compra realizada", "tiempo": "hace 5 min"},
        {"usuario": "Carlos López", "accion": "Registro nuevo", "tiempo": "hace 12 min"},
        {"usuario": "María Rodríguez", "accion": "Actualización perfil", "tiempo": "hace 1 hora"}
    ]
    
    return templates.TemplateResponse(
        "dashboard.html",
        {
            "request": request,
            "fecha_actual": datetime.now(),
            "estadisticas": estadisticas,
            "actividades": actividad_reciente
        }
    )

El template correspondiente procesa estos datos para crear una interfaz informativa:

<!-- templates/dashboard.html -->
{% extends "base.html" %}

{% block contenido %}
    <h1>Dashboard - {{ fecha_actual.strftime('%d/%m/%Y') }}</h1>
    
    <div class="estadisticas">
        <div class="stat-card">
            <h3>{{ estadisticas.usuarios_activos }}</h3>
            <p>Usuarios Activos</p>
        </div>
        <div class="stat-card">
            <h3>{{ estadisticas.ventas_hoy }}</h3>
            <p>Ventas Hoy</p>
        </div>
        <div class="stat-card">
            <h3>${{ "%.2f"|format(estadisticas.ingresos_mes) }}</h3>
            <p>Ingresos del Mes</p>
        </div>
    </div>
    
    <h2>Actividad Reciente</h2>
    <ul class="actividad-lista">
    {% for actividad in actividades %}
        <li>
            <strong>{{ actividad.usuario }}</strong>: 
            {{ actividad.accion }} 
            <em>({{ actividad.tiempo }})</em>
        </li>
    {% endfor %}
    </ul>
{% endblock %}

Esta integración entre FastAPI y Jinja2 proporciona una base sólida para crear aplicaciones web dinámicas que combinan la potencia del backend Python con interfaces de usuario atractivas y funcionales.

Empezar curso de FastAPI

Lecciones de este módulo de FastAPI

Lecciones de programación del módulo Templates del curso de FastAPI.

Ejercicios de programación en este módulo de FastAPI

Evalúa tus conocimientos en Templates con ejercicios de programación Templates de tipo Test, Puzzle, Código y Proyecto con VSCode.