Cuando desarrollamos un sitio web, es común tener que manejar imágenes o archivos de tipo HTML, CSS, JS, etc. A este tipo de archivos se les conoce como
estáticos; y
es recomendable servirlos de manera nativa, ya que el servidor no está construido para eso.
Existen varias técnicas o hacks para lograr que nuestro framework, Django en este caso, haga este trabajo por nosotros, pero no son las mejores prácticas de un
administrador de servidores profesional. Sin embargo, otra opción que tenemos es utilizar otro servicio ajeno al servidor de Django, que se encargue de responder y servir todas las peticiones de archivos estáticos. Esto nos servirá
para agilizar y mejorar la respuesta de nuestro sitio.
Amazon ofrece, dentro de la suite de productos de Amazon Web Services, un servicio para manejar archivos estáticos llamado
Amazon S3. En este artículo, te enseñaré paso a paso cómo lograr servir los estáticos de un proyecto de Django usando este servicio.
1.- Como primer paso, debes entrar a la consola de Amazon Web Services en
console.aws.amazon.com
2.- En la sección de
Storage & Content Delivery debes seleccionar S3 y crear un
Bucket nuevo. Para este ejercicio usaré
platzis3 como nombre.
3.- De nuevo en la consola de AWS, en la sección de
Administración y Seguridad, debes seleccionar
Identity & Access Management (IAM).
4.- Dentro de IAM ve a la sección de usuarios y crea un nuevo usuario. Para nuestro ejemplo usaré
platzis3 como username.
5.- Cuando creemos el usuario, nos mostrará una pantalla con las credenciales, donde se incluye el
Access Key IDy el
Secret Access Key. Esta será la primera y única vez en la que podrás ver estas claves, así que te recomiendo almacenarlas, recordarlas o anotarlas. Es importante tenerlas a la mano porque las usarás en la configuración de Django.

6.- Para este punto necesitaremos el
Access Key ID, el
Secret Access Key y el
User ARN que podrás encontrar accediendo a la sección de usuarios y luego dando clic sobre el usuario que creaste.

7.- Ya con estos datos, ahora le daremos permisos a nuestro nuevo usuario para que pueda editar, visualizar y subir archivos a nuestro
bucket. Para hacer esto tenemos que agregar una nueva política en la sección
Permissions con el botón de
Attach Policy. Ahí, debemos seleccionar la opción que diga
AmazonS3FullAccess.

8.- Ahora, regresa a la consola de S3 y dentro de nuestro
bucket en la sección de
Bucket properties > Permissions agregamos una nueva política con el formato del siguiente JSON.
{
"Statement": [
{
"Sid":"PublicReadForGetBucketObjects",
"Effect":"Allow",
"Principal": {
"AWS": "*"
},
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::BUCKET-NAME/*"
]
},
{
"Action": "s3:*",
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::BUCKET-NAME",
"arn:aws:s3:::BUCKET-NAME/*"
],
"Principal": {
"AWS": [
"USER-ARN"
]
}
}
]
}
En el JSON incluímos dos declaraciones dentro de un arreglo. La primera es la que hace nuestro que
bucket,
platzis3, esté disponible para lectura por cualquier persona en internet.
La segunda declaración le da acceso de lectura, escritura y edición al usuario de AWS que coincida con el ARN que hayamos puesto ahí. Por lo que queda así:
- En la línea 10, 17 y 18 se agrega el bucket name
- En la línea 22 se agrega el User ARN

9.- Hasta este punto habilitamos a nuestro usuario para escribir y a nuestro
bucket para poder ser consultado. Para poder conectarnos a S3 desde Django necesitaremos instalar dos librerías primero,
django-storages y
boto. Esto lo hacemos corriendo el siguiente comando (espero que estén usando entornos virtuales):
$ pip install django-storages boto
10.- Ahora debemos agregar
storages a nuestras
installed apps:

11.- Y, después, agregamos las siguientes líneas a nuestro
settings.py:

- El valor de STATIC_URL es un string con la url del bucket, en el caso del ejemplo es: platzis3.s3-website-us-west-1.amazonaws.com
- También cambiamos el almacenaje de estáticos por el de Amazon S3.
- El valor de AWS_STORAGE_BUCKET_NAME es un string con el nombre del bucket, en este ejemplo es platzis3.
- Los valores de AWS_ACCESS_KEY_ID y AWS_SECRET_ACCESS_KEY también son strings con las credenciales del usuario que habíamos creado. Para el ejemplo usé variables del sistema para no exponer las claves a la hora de publicarlo en Github.
12.- Por último, nos queda correr el comando que mandará todos nuestros estáticos al bucket en Amazon S3:
$ python manage.py collectstatic
El resultado final, si analizamos el HTML de alguna de nuestras vistas, se verá así:

Y el contenido se verá escrito dentro de nuestro bucket:
Si estamos haciendo cambios en desarrollo a los archivos estáticos, tendremos que hacer un collectstatic para poder visualizarlos. Esto puede volvernos locos si lo único que queremos hacer es un pequeño cambio a un color, por ejemplo. Pero, si agregamos un simple
if que valide si estamos o no en producción, nos ahorraremos mucha desesperación:

¿Quieres ser un experto en Amazon S3? Tenemos un
curso de administración de servidores que cubre Amazon Web Services, Heroku, Docker, Azure, Rackspace y todo lo que necesitas para ser un DevOps profesional. ¡
Apuntate ahora!