Mira la lección en vídeo
Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.
Desbloquear Plan PlusConfiguración de StaticFiles
FastAPI incluye soporte nativo para servir archivos estáticos como CSS, JavaScript, imágenes y otros recursos que necesitan las páginas web. Estos archivos no cambian dinámicamente y se sirven directamente al navegador sin procesamiento adicional.
Para habilitar el servicio de archivos estáticos, necesitamos usar la clase StaticFiles de FastAPI y montarla en nuestra aplicación. Esta configuración permite que el servidor web sirva archivos desde un directorio específico de nuestro proyecto.
Instalación de dependencias
Antes de configurar los archivos estáticos, necesitamos instalar python-multipart, que es requerido por StaticFiles:
pip install python-multipart
Estructura de directorios
La práctica habitual es crear un directorio llamado static
en la raíz del proyecto para almacenar todos los recursos estáticos:
mi_proyecto/
├── main.py
├── templates/
│ └── index.html
└── static/
├── css/
│ └── styles.css
├── js/
│ └── script.js
└── images/
└── logo.png
Configuración básica
Para configurar StaticFiles en FastAPI, importamos la clase y la montamos en nuestra aplicación usando el método mount():
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.requests import Request
app = FastAPI()
# Configurar archivos estáticos
app.mount("/static", StaticFiles(directory="static"), name="static")
# Configurar templates
templates = Jinja2Templates(directory="templates")
@app.get("/")
async def home(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
El método mount() recibe tres parámetros importantes:
- Ruta de montaje (
"/static"
): La URL base donde estarán disponibles los archivos - StaticFiles con el directorio local (
directory="static"
) - Nombre (
name="static"
): Identificador interno para referenciar esta configuración
Acceso a los archivos estáticos
Una vez configurado, los archivos del directorio static
estarán accesibles a través de URLs que siguen el patrón /static/ruta_del_archivo
:
static/css/styles.css
→http://localhost:8000/static/css/styles.css
static/js/script.js
→http://localhost:8000/static/js/script.js
static/images/logo.png
→http://localhost:8000/static/images/logo.png
Ejemplo completo con archivos CSS
Creemos un ejemplo práctico con un archivo CSS. Primero, el archivo styles.css en static/css/
:
/* static/css/styles.css */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
text-align: center;
}
El template HTML que usa este CSS:
<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head>
<title>Mi Aplicación FastAPI</title>
<link rel="stylesheet" href="/static/css/styles.css">
</head>
<body>
<div class="container">
<h1>Bienvenido a FastAPI</h1>
<p>Esta página usa archivos estáticos para el diseño.</p>
</div>
</body>
</html>
Configuración con múltiples directorios
También es posible montar múltiples directorios estáticos con diferentes rutas de acceso:
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
# Archivos CSS y JS
app.mount("/assets", StaticFiles(directory="static"), name="assets")
# Imágenes en directorio separado
app.mount("/media", StaticFiles(directory="uploads"), name="media")
Esta configuración permite organizar mejor los recursos según su tipo y tener URLs más específicas para cada categoría de archivos estáticos.
Enlazar CSS y JavaScript en templates
Guarda tu progreso
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
Una vez configurados los archivos estáticos, el siguiente paso es enlazarlos correctamente en nuestros templates HTML. FastAPI con Jinja2 ofrece varias formas de referenciar estos recursos, desde enlaces directos hasta el uso de funciones auxiliares que generan las URLs automáticamente.
Enlaces directos a archivos estáticos
La forma más directa de enlazar archivos CSS y JavaScript es usando rutas absolutas que apunten al directorio estático configurado:
<!-- templates/base.html -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mi Aplicación</title>
<!-- Enlace directo a CSS -->
<link rel="stylesheet" href="/static/css/styles.css">
<link rel="stylesheet" href="/static/css/components.css">
</head>
<body>
<div class="container">
<h1>Contenido de la página</h1>
</div>
<!-- Enlaces directos a JavaScript -->
<script src="/static/js/utils.js"></script>
<script src="/static/js/main.js"></script>
</body>
</html>
Uso de url_for para generar URLs
Jinja2 proporciona la función url_for() que genera automáticamente las URLs correctas basándose en el nombre que asignamos al montar los archivos estáticos. Esta aproximación es más robusta porque se adapta automáticamente si cambiamos la configuración:
<!-- templates/dashboard.html -->
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Dashboard</title>
<!-- Usando url_for para CSS -->
<link rel="stylesheet" href="{{ url_for('static', path='/css/dashboard.css') }}">
<link rel="stylesheet" href="{{ url_for('static', path='/css/forms.css') }}">
</head>
<body>
<div class="dashboard">
<h1>Panel de Control</h1>
<div class="widgets">
<!-- Contenido del dashboard -->
</div>
</div>
<!-- Usando url_for para JavaScript -->
<script src="{{ url_for('static', path='/js/charts.js') }}"></script>
<script src="{{ url_for('static', path='/js/dashboard.js') }}"></script>
</body>
</html>
El parámetro 'static' corresponde al nombre que definimos en la configuración (name="static"
), y path especifica la ruta relativa dentro del directorio estático.
Ejemplo práctico con múltiples archivos
Creemos un ejemplo completo que demuestre cómo organizar y enlazar múltiples archivos CSS y JavaScript. Primero, los archivos estáticos:
static/css/base.css:
/* Estilos base para toda la aplicación */
* {
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
static/css/forms.css:
/* Estilos específicos para formularios */
.form-group {
margin-bottom: 20px;
}
.form-control {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.btn {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
}
static/js/validation.js:
// Funciones de validación de formularios
function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function validateForm(formData) {
const errors = [];
if (!formData.name || formData.name.trim().length < 2) {
errors.push('El nombre debe tener al menos 2 caracteres');
}
if (!validateEmail(formData.email)) {
errors.push('El email no tiene un formato válido');
}
return errors;
}
static/js/app.js:
// Funcionalidad principal de la aplicación
document.addEventListener('DOMContentLoaded', function() {
const forms = document.querySelectorAll('form');
forms.forEach(form => {
form.addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(form);
const data = Object.fromEntries(formData);
const errors = validateForm(data);
if (errors.length > 0) {
showErrors(errors);
} else {
submitForm(data);
}
});
});
});
function showErrors(errors) {
const errorContainer = document.getElementById('errors');
errorContainer.innerHTML = errors.map(error =>
`<div class="alert alert-error">${error}</div>`
).join('');
}
Template que utiliza todos los archivos
templates/contact.html:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Contacto - Mi Aplicación</title>
<!-- Archivos CSS en orden de importancia -->
<link rel="stylesheet" href="{{ url_for('static', path='/css/base.css') }}">
<link rel="stylesheet" href="{{ url_for('static', path='/css/forms.css') }}">
</head>
<body>
<div class="container">
<h1>Formulario de Contacto</h1>
<div id="errors"></div>
<form id="contactForm">
<div class="form-group">
<label for="name">Nombre:</label>
<input type="text" id="name" name="name" class="form-control" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" class="form-control" required>
</div>
<div class="form-group">
<label for="message">Mensaje:</label>
<textarea id="message" name="message" class="form-control" rows="5" required></textarea>
</div>
<button type="submit" class="btn">Enviar Mensaje</button>
</form>
</div>
<!-- JavaScript al final del body para mejor rendimiento -->
<script src="{{ url_for('static', path='/js/validation.js') }}"></script>
<script src="{{ url_for('static', path='/js/app.js') }}"></script>
</body>
</html>
Ruta de FastAPI correspondiente
Para que este template funcione correctamente, necesitamos la ruta correspondiente en FastAPI:
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
app = FastAPI()
# Configuración de archivos estáticos
app.mount("/static", StaticFiles(directory="static"), name="static")
# Configuración de templates
templates = Jinja2Templates(directory="templates")
@app.get("/contact")
async def contact_page(request: Request):
return templates.TemplateResponse("contact.html", {"request": request})
Buenas prácticas para enlazar archivos
Al enlazar archivos CSS y JavaScript en templates, es recomendable seguir estas prácticas:
- Orden de carga: Los archivos CSS van en el
<head>
, los JavaScript al final del<body>
- Dependencias: Cargar primero los archivos base y luego los específicos
- Consistencia: Usar siempre
url_for()
o siempre rutas directas, no mezclar ambos enfoques - Organización: Agrupar archivos relacionados en subdirectorios (
css/
,js/
,images/
)
Esta configuración permite que nuestras páginas web tengan estilos visuales atractivos y funcionalidad interactiva, manteniendo una estructura organizada y fácil de mantener.
Aprendizajes de esta lección de FastAPI
- Comprender cómo configurar la clase StaticFiles para servir archivos estáticos en FastAPI.
- Organizar la estructura de directorios para recursos estáticos en un proyecto FastAPI.
- Enlazar correctamente archivos CSS y JavaScript en templates HTML usando rutas absolutas y la función url_for.
- Implementar múltiples directorios estáticos con diferentes rutas de acceso para una mejor organización.
- Aplicar buenas prácticas en la carga y organización de archivos estáticos para mejorar la mantenibilidad y rendimiento.
Completa este curso de FastAPI y certifícate
Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs