Django se centra en la parte dinámica de una aplicación web, pero una página completa también necesita imágenes, hojas de estilo y JavaScript. En proyectos pequeños basta con copiar estos ficheros a cualquier carpeta accesible, pero cuando crecen y se dividen en varias apps la tarea se vuelve engorrosa. La aplicación django.contrib.staticfiles automatiza la recopilación de todos los recursos estáticos en un único punto de acceso para el servidor.
Configuración básica
- Ubicación de los ficheros. Por defecto,
staticfilesbusca dentro de cada app que esté enINSTALLED_APPSuna sub-carpeta llamadastatic/. También puedes añadir rutas extra conSTATICFILES_DIRSy cambiar la estrategia de búsqueda medianteSTATICFILES_FINDERS. - Activar la aplicación. Asegúrate de que
django.contrib.staticfilesesté enINSTALLED_APPS. La URL pública por defecto comenzará con/static/(STATIC_URL). - En las plantillas utiliza la variable
STATIC_URL: ```
Pasos para producción
- Define
STATIC_URLcon la ruta pública definitiva (p. ej.https://cdn.miapp.com/static/). - Indica el destino físico con
STATIC_ROOT: ``` STATIC_ROOT = '/var/www/miapp/static' - Ejecuta el recolector: ```
python manage.py collectstatic
Esto copiará todos los ficheros estáticos al directorio anterior. - Configura tu servidor web para que sirva el contendio de
STATIC_ROOTen la URL definida enSTATIC_URL.
Referenciar recursos en plantillas sin rutas absolutas
Introducir URLs absolutas en los templates dificulta los cambios futuros. La solución pasa por usar STATIC_URL o la etiqueta {% static %}.
Mediante context processor
Si django.core.context_processors.static está en TEMPLATE_CONTEXT_PROCESSORS (lo está por defecto) puedes escribir:
<link rel="stylesheet" href="{{ STATIC_URL }}css/main.css">
Recuerda pasar RequestContext a la plantilla o usar un render genérico.
Mediante la etiqueta {% static %}
{% load static %}
<img src="{% static 'img/logo.png' %}">
<script src="{% static ruta_js_dinamica %}"></script>
Servir ficheros estáticos durante el desarrollo
El comando runserver activa automáticamente una vista auxiliar que sirve los recursos cuando DEBUG=True. Si utilizas otro servidor local, añade en urls.py:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
Esta línea solo funciona con DEBUG=True y STATIC_URL distinto de una URL absoluta.
Servir carpetas adicionales
Para ficheros subidos por usuarios (por ejemplo, MEDIA_ROOT) puedes usar la vista serve:
from django.conf import settings
from django.views.static import serve
if settings.DEBUG:
from django.conf.urls import url
urlpatterns += [
url(r'^media/(?P<path>.*)$', serve, {
'document_root': settings.MEDIA_ROOT,
}),
]
O de forma más concisa:
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Despliegue en producción
El flujo habitual consiste en:
- Ejecutar
collectstatic. - Copiar o sincronizar
STATIC_ROOTal servidor que servirá los ficheros estáticos.
Mismo servidor que Django
Tras ejecutar collectstatic en el servidor, apunta tu servidor web (Apache, Nginx…) a la carpeta resutlante.
Servidor independiente
La mayoría de sitios grandes separan la carga de contenido estático en un servidor dedicado (Nginx, lighttpd, etc.). El proceso suele automatizarse con herramientas como Fabric:
from fabric.api import *
env.hosts = ['static.miapp.com']
env.local_static = '/tmp/static'
env.remote_static = '/var/www/static'
def publicar():
local('python manage.py collectstatic --noinput')
local('rsync -av --delete {}/ static@{}:{}/'.format(
env.local_static, env.hosts[0], env.remote_static))
Con esta rutina solo se transfieren los cambios, reduciendo el tiempo de despliegue.