CAPÍTULO 9 · El mismo proyecto llega a Azure
La página necesita sus archivos cuando deja el desarrollo
Una página sin estilos puede dar la impresión de que la publicación falló por completo, aunque Django haya respondido correctamente. En desarrollo, runserver facilita servir los archivos fuente. Al pasar a producción necesitamos distinguir la preparación de esos recursos de la ejecución de las vistas que producen HTML.
En el flujo del equipo ejecutamos collectstatic antes de empaquetar. El comando reúne la salida en STATIC_ROOT usando la configuración correspondiente, y el mecanismo de producción se encarga de servirla. WhiteNoise forma parte de esa ruta en el ejemplo. La salida recolectada debe acompañar al código y conservar el manifiesto que relaciona los nombres de los recursos.
Revisamos que la preparación termine sin errores y que los archivos existan. No basta con confiar en que se ven bien en el PC. Con los estáticos listos ya podemos construir una entrega: una estructura concreta que contendrá lo necesario para arrancar, sin arrastrar todo lo que utilizamos durante el desarrollo.
Leer esta parte dentro del relato completo →DEL RELATO A LA PRÁCTICA
Vamos a desarrollar esta decisión con su mapa, explicación, código y ejercicio.
MIRA · CONECTA · COMPRENDE
La fábrica de estáticos
Las flechas resumen el recorrido conceptual. Los controles y dependencias se detallan debajo.
Selecciona una pieza para destacar su responsabilidad.
Leer la explicación del mapa
- Fuentes. CSS JS e imágenes
- collectstatic. Reúne archivos del build
- STATIC_ROOT. Conserva salida generada
- Servidor. Entrega recursos estáticos
01 / EL PROBLEMA
¿Para qué sirve?
Con DEBUG=True los estilos pueden funcionar localmente y desaparecer al publicar. El servidor de producción necesita una estrategia explícita para servirlos.
02 / COMPRENDER
El concepto, explicado
static/ contiene los archivos fuente. collectstatic reúne archivos de las apps y de STATICFILES_DIRS en STATIC_ROOT. Esa salida no debe estar incluida a su vez en STATICFILES_DIRS.
WhiteNoise se coloca después de SecurityMiddleware. Para Django 5.2 usa STORAGES["staticfiles"], no el antiguo STATICFILES_STORAGE. El manifiesto da nombres con hash para que el navegador distinga versiones.
En la ruta manual del equipo ejecutamos collectstatic antes de empaquetar e incluimos su salida. Oryx instalará los paquetes en Linux, mientras DISABLE_COLLECTSTATIC=true evita repetir esta fase. Otra ruta válida es recolectar durante el build remoto, con manage.py en la raíz o un comando explícito; debe escogerse una ruta y comprobar su resultado.
WhiteNoise no es el almacén de uploads. Los archivos de usuarios y los datos persistentes requieren una ubicación durable. Un redeploy debe poder reconstruir estáticos sin perder datos.
En desarrollo, runserver con django.contrib.staticfiles y DEBUG=True sirve los archivos fuente para facilitar el trabajo. En producción, Gunicorn no sustituye ese servicio: collectstatic reúne los archivos, y WhiteNoise u otro servidor los entrega. Recolectar y servir son responsabilidades distintas.
El mismo conjunto de estáticos debe construirse con las apps y el backend de producción. Si un ajuste depende de variables, prepara el entorno antes de ejecutar el comando; no publiques el .env. STATIC_ROOT y STATICFILES_DIRS no deben señalar la misma carpeta.
Una página puede devolver 200 y aun así perder CSS, JavaScript o imágenes. Verifica al menos un recurso con hash referenciado desde HTML y su respuesta; vuelve a construir el paquete cuando cambie una fuente estática.
03 / CONSTRUIR
Implementación paso a paso
- Declara STATIC_URL, STATIC_ROOT y solo directorios fuente existentes.
- Incluye WhiteNoise como dependencia y ordena su middleware.
- Configura el backend de staticfiles en STORAGES.
- Ejecuta collectstatic en el entorno de construcción.
- Comprueba CSS, JS e imágenes con DEBUG=False y después de un redeploy.
04 / APLICAR
Ejemplo en SensorHub
# Fragmento de production.py para Django 5.2
from .base import *
STATIC_URL = "/static/"
STATIC_ROOT = BASE_DIR / "staticfiles"
STATICFILES_DIRS = [BASE_DIR / "static"]
STORAGES = {
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
"staticfiles": {
"BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage"
},
}
# base debe tener SecurityMiddleware en primer lugar.
# Añadir una sola vez si no estaba ya configurado:
MIDDLEWARE = [MIDDLEWARE[0], "whitenoise.middleware.WhiteNoiseMiddleware", *MIDDLEWARE[1:]]
# Terminal del entorno de construcción con variables preparadas:
# python manage.py collectstatic --noinput --settings=config.settings.productionCómo leer el ejemplo
- El backend default es ilustrativo; ajusta media a almacenamiento persistente si tu aplicación recibe uploads.
- Un Missing staticfiles manifest entry requiere revisar rutas y construcción, no desactivar seguridad.
Error habitual
No muevas requirements.txt a una ubicación que impida detectarlo ni copies el venv de Windows al runtime Linux.
05 / PRACTICAR
Tu turno
La página abre pero las ilustraciones dan 404: ¿qué compruebas primero?
Ver solución orientativa
Revisa el resultado de collectstatic, STATIC_ROOT, nombres usados por static y la presencia de WhiteNoise. Después confirma el build desplegado.
06 / VERIFICAR
Cómo sabes que funciona
- Los archivos responden 200 con DEBUG=False.
- Repetir el build no depende de archivos locales no versionados.
Para profundizar
Documentación oficial para comprobar configuración, permisos y condiciones vigentes. Revisión del tema: 11 de octubre de 2026.
CONTINUAR LA EXPERIENCIA
El siguiente paso del recorrido:
deploy.zip: carpeta del proyecto y estáticos preparados →Continuar en modo relato