Introducción
Las Progressive Web Apps (PWA) combinan lo mejor de la web y de las apps nativas: cargan al instante, funcionan sin conexión y pueden instalarse en el dispositivo del usuario. Transformar tu proyecto Django en una PWA no es complicado, pero sí requiere atender a varios detalles. En este post recorreremos, paso a paso, los “tips” esenciales para lograrlo de forma clara y sin dolor de cabeza.
Requisitos Previos
- Django 4.x o superior
- Navegador con soporte para Service Workers (todos los modernos)
- Servidor HTTPS en producción (los Service Workers solo se registran en contexto seguro)
1. Instalar las dependencias básicas
La ruta “manual” te da control total, pero si quieres acelerar el proceso,
django-pwa
o
django-serviceworker
hacen gran parte del trabajo pesado.
pip install django-pwa
En
settings.py
añades el paquete y la app estática:
INSTALLED_APPS = [ ... "django.contrib.staticfiles", "pwa", # <-- nuevo ]
2. Crear y exponer el manifest
El
manifest.json
contiene metadatos para que el navegador “instale” tu app. Guárdalo en tu carpeta
static
y enlázalo en
base.html
.
{ "name": "Mi Django PWA", "short_name": "DjangoPWA", "start_url": "/", "display": "standalone", "scope": "/", "theme_color": "#0e4c92", "background_color": "#ffffff", "icons": [ { "src": "/static/img/icon-192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/static/img/icon-512.png", "sizes": "512x512", "type": "image/png" } ] }
En tu plantilla base:
<link rel="manifest" href="{% static 'manifest.json' %}">
3. Registrar el Service Worker
El Service Worker intercepta peticiones y decide qué cachear. Crea
static/sw.js
:
self.addEventListener("install", event => { event.waitUntil( caches.open("v1").then(cache => cache.addAll([ "/", "/static/css/main.css", "/static/js/main.js", ])) ); }); self.addEventListener("fetch", event => { event.respondWith( caches.match(event.request).then(response => response || fetch(event.request) ) ); });
Luego regístralo en tu plantilla:
<script> if ("serviceWorker" in navigator) { window.addEventListener("load", () => { navigator.serviceWorker.register("{% static 'sw.js' %}"); }); } </script>
4. Ajustar cabeceras y seguridad
SECURE_SSL_REDIRECT = True
en producción. - CSP: bloquea recursos externos no necesarios.
X-Frame-Options
y Referrer-Policy
coherentes.
5. Añadir estrategias de caché inteligentes
No todo debe ir al mismo “bucket”. Mi combo favorito:
- Cache First para assets estáticos y fuentes.
- Stale-While-Revalidate para vistas HTML frecuentemente actualizadas.
- Network First para endpoints críticos (API con datos frescos).
6. Habilitar modo offline “agradable”
Sirve una página HTML mínima cuando la red falla:
self.addEventListener("fetch", event => { event.respondWith( fetch(event.request).catch(() => caches.match("/offline/")) ); });
7. Testear con Lighthouse
Ejecuta Chrome DevTools ► Lighthouse. Apunta a una puntuación PWA > 90. Ajusta lo que falte (service worker activo, ratio de contraste, tiempos de carga).
8. Configurar despliegue CI/CD y versioning
Cada build debe “romper” la caché vieja. Buen truco: inyecta el
GIT_SHA
en el nombre del Service Worker o en la versión de cache (
caches.open("v{{ GIT_SHA }}")
). Así evitas que los usuarios queden atascados con JS obsoleto.
9. Consigue ese icono “Add to Home Screen”
Para que Chrome muestre el mini‑banner debes:
- Tener HTTPS.
- Tener manifest válido con
start_url
y icons de 192 y 512 px. - Service Worker con al menos un
fetch
o cache
activo.
10. Bonus: Push Notifications
Si tu app lo necesita, integra
django-webpush
. El flujo general:
- Generas claves VAPID.
- Registras permisos en el cliente.
- Envías notificación desde una
view
o un Celery task
.
Conclusión
Convertir tu Django en PWA es cuestión de añadir un par de ficheros estáticos, registrar un Service Worker y cuidar la caché. Mi opinión personal, Capi: vale mucho la pena. La sensación de “app nativa” mejora la retención y, con HTTPS+Service Worker bien configurado, ganas velocidad y resiliencia gratis. Empieza simple, itera, y pronto tu proyecto estará listo para ocupar un lugar de honor en la pantalla de inicio de tus usuarios.
¡Nos leemos en el próximo post y, como siempre, rompe esos logs antes de que te rompan a ti!