Entrega de archivos estáticos en Python con Django, AWS S3 y WhiteNoise

     

    Introducción

    Los sitios web generalmente necesitan archivos adicionales como imágenes, CSS y archivos JavaScript que son necesarios para representar páginas web completas en un navegador. En proyectos pequeños, podemos trabajar proporcionando rutas absolutas a nuestros recursos o escribiendo funciones CSS y JavaScript en línea en los archivos HTML. Esto no solo va en contra de las mejores prácticas de codificación, sino que también se complica cuando manejamos proyectos más grandes, especialmente con múltiples aplicaciones.

    En Django, los archivos necesarios para la experiencia interactiva del usuario, la presentación de documentos y las páginas web funcionales se denominan archivos estáticos.

    En este artículo, veremos cómo podemos tratar con múltiples conjuntos de archivos estáticos proporcionados por cada aplicación para personalizar la apariencia de un sitio web.

    Configuración de archivos estáticos

    Django proporciona una enorme flexibilidad sobre cómo puede servir los archivos estáticos. Cubriremos el uso de archivos estáticos en el desarrollo local, así como en la producción, que es un poco más compleja. Primero lo primero, hagamos la configuración básica.

    Django proporciona django.contrib.staticfiles para ayudarlo a recopilar archivos estáticos de cada una de sus aplicaciones (y cualquier otro lugar que especifique) en una sola ubicación que se puede servir fácilmente en producción.

    En tus settings.py archivo, tu INSTALLED_APPS debería verse así:

    INSTALLED_APPS = [
        'django.contrib.auth',
        'django.contrib.sites',
        'django.contrib.contenttypes',
        'django.contrib.admin',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles', # To serve static files
    ]
    

    STATIC_ROOT es la ruta que define dónde se recopilarán sus archivos estáticos. Proporcionaremos un camino absoluto para STATIC_ROOT en settings.py.

    Para hacer esto, usaremos el os módulo dirname() función para obtener el nombre del directorio en el que nos gustaría alojar estos archivos y definir la ruta:

    import os
    
    PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
    

    Luego, debe especificar un STATIC_URL que es la URL utilizada cuando se hace referencia a archivos estáticos. Debe terminar con / si se establece en cualquier valor excepto None. La siguiente ruta significa que los archivos estáticos se almacenarán en la ubicación http://localhost:8000/static/ o http://127.0.0.1:8000/static/:

    STATIC_URL = '/static/'
    

    Django tiene una lista de buscadores como STATICFILES_FINDERS que utiliza para localizar archivos estáticos. Uno de los buscadores predeterminados es AppDirectoriesFinder que busca una carpeta llamada static dentro de cada uno de tus INSTALLED_APPS.

    Por ejemplo, si su proyecto contiene una aplicación llamada users, puede crear un directorio como project_name/users/static/index.css para agregar archivos CSS relacionados con esa aplicación.

    Aunque esto funciona, es una mejor idea crear otro subdirectorio con el nombre de su aplicación, como project_name/users/static/users/index.css. Esto es importante cuando tenemos dos o más archivos estáticos con nombres similares.

    Consideremos que tienes un index.css en cada aplicación, cada una de las cuales contiene diferentes estilos CSS. Django buscará el primero index.css podría encontrar en app/static/ directorios. No podrá distinguir entre varios index.css que tenemos en cada aplicación static directorio. Por eso creamos un subdirectorio con el nombre de la aplicación app/static/app/.

    Además, la mayoría de los proyectos tienen varias aplicaciones que pueden tener archivos estáticos comunes, por lo que generalmente es mejor crear una carpeta static en el directorio raíz de su proyecto en lugar de hacer un static carpeta en cada aplicación:

    Para utilizar un lugar común para todos los archivos estáticos en el directorio de su proyecto, necesitamos configurar STATICFILES_DIRS para informar a Django sobre nuestro nuevo directorio porque AppDirectoriesFinder buscará static en app directorios solamente. También podemos definir múltiples ubicaciones para nuestros archivos estáticos.

    Este es el lugar para definir las carpetas estáticas de proyectos individuales si tiene varias:

    STATICFILES_DIRS = (
        os.path.join(PROJECT_ROOT, 'static'),
        # Extra lookup directories for collectstatic to find static files
    )
    

    Tenga en cuenta que STATICFILES_DIRS solo funcionará si no quita FileSystemFinder desde STATICFILES_FINDERS.

    Como breve recapitulación, nuestro settings.py incluir:

    import os
    
    PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
    STATIC_ROOT  = os.path.join(PROJECT_ROOT, 'staticfiles')
    STATIC_URL = '/static/'
    
    # Extra lookup directories for collectstatic to find static files
    STATICFILES_DIRS = (
        os.path.join(PROJECT_ROOT, 'static'),
    )
    

    Los archivos estáticos están listos para usarse en su proyecto. Solo necesitamos cargar el static etiqueta de plantilla por {% load static %} y luego usa el static etiqueta de plantilla para crear la URL de la ruta relativa dada. Veamos cómo podemos usar archivos estáticos en nuestro archivo de plantilla. base.html:

    <!doctype html>
    {% load static %}
    <html lang="en">
        {% include 'head.html' %}
     <style>
        body{
          background: url('{% static "bg.png" %}') no-repeat center center fixed; 
            -webkit-background-size: cover;
            -moz-background-size: cover;
            -o-background-size: cover;
            background-size: cover;
        }
     </style>
      <body>
          <div class="row justify-content-center">
            <div class="col-8">
                <h1 class="mainbtn">MY CUSTOM CSS CLASS</h1>
              {% block content %}
              <hr class="mt-0 mb-4">
              {% endblock %}
            </div>
          </div>
        </div>
      </body>
    </html>
    

    los base.html incluye una head.html plantilla para una segregación adecuada, ya que los proyectos más grandes suelen contener un código extenso en head etiquetas los mainbtn clase para h1 se define en el static/index.css archivo. La imagen de fondo bg.png también está presente en static directorio.

    los head.html Se ve como esto:

    <head>
        {% block css_block %}{% endblock %}
        {% load static %}
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        
        <link rel="stylesheet" href="{% static 'css/index.css' %}">
        <script src="{% static 'js/functions.js' %}"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        
        <title>{% block title %} Title to be changed in included files {% endblock %}</title>
    </head>
    

    Entrega de archivos estáticos

    Además de las configuraciones anteriores, también necesitamos servir los archivos estáticos. Lo hace automáticamente Django runserver comando si Debug = True. Debe utilizar este método en la fase de desarrollo ya que es fácil, sin embargo, no se recomienda para producción porque es ineficiente e inseguro.

    Django viene con un comando incorporado collecstatic. Compila todos los archivos estáticos en un solo directorio STATIC_ROOT que ya configuramos. La pieza final es el motor de almacenamiento que se utiliza al recopilar archivos estáticos con el collectstatic mando. El motor de almacenamiento se puede configurar mediante STATICFILES_STORAGE. Django tiene su propio motor de almacenamiento, por lo que el valor predeterminado de STATICFILES_STORAGE se establece en django.contrib.staticfiles.storage.StaticFilesStorage.

    Archivos estáticos en producción

    Hay dos pasos principales para colocar archivos estáticos en un entorno de producción:

    • Ejecutar el collectstatic comando cada vez que cambian los archivos estáticos
    • Arreglos para STATIC_ROOT para ser movido al servidor de archivos estáticos y servido

    los post_process() método del Storage la clase puede encargarse del segundo paso, pero realmente depende de su motor de almacenamiento, es decir STATICFILES_STORAGE.

    Nota: Debe saber que el servicio de archivos estáticos en cada producción será diferente debido a la diferencia en los entornos, pero la idea básica y los pasos siguen siendo los mismos. Hay tres tácticas principales para manejar los archivos estáticos en producción:

    • Sirva los archivos estáticos y el sitio desde el mismo servidor: Utilice este método si desea que sus archivos estáticos sean servidos desde el servidor que ya está ejecutando su aplicación web. A pesar de su posible problema de rendimiento, podría ser rentable ya que solo necesita pagar por el alojamiento de un servidor. Para hacer esto, envíe su código al servidor de implementación y luego ejecute collectstatic para copiar todos los archivos a STATIC_ROOT. Por último, configure su servidor web para servir los archivos estáticos en STATIC_URL.
    • Sirviendo archivos estáticos desde un servidor dedicado: Las opciones más comunes para servidores de archivos estáticos dedicados son nginx y versión reducida de Apache. La aplicación web se ejecuta en un servidor completamente diferente, mientras que sus archivos estáticos se implementan en un servidor dedicado que brinda un rendimiento más rápido en general. correr collectstatic localmente siempre que los archivos estáticos cambien y luego empuje STATIC_ROOT al directorio de su servidor dedicado que se está sirviendo. Para obtener instrucciones detalladas, debe consultar la documentación del servidor correspondiente.
    • Entrega de archivos estáticos desde un servicio en la nube: Otra táctica común es entregar archivos estáticos de un proveedor de almacenamiento en la nube como Amazon, Microsoft Azure y Alibaba Cloud.

    Veamos cómo podemos usar Amazon S3 para este propósito. Primero, instale dos bibliotecas de Python usando estos comandos:

    $ python -m pip install boto3
    $ pip install django-storages
    

    los boto3 library es un cliente API público para acceder a Amazon S3 y otros servicios web de Amazon (AWS). los django-storages gestiona backends de almacenamiento como Amazon S3, OneDrive, etc. Se conecta a la API de backend de almacenamiento Django incorporada. También necesitará agregar storages en tus INSTALLED_APPS. Nuestra INSTALLED_APPS como se ve así por ahora:

    INSTALLED_APPS = [
        'django.contrib.auth',
        'django.contrib.sites',
        'django.contrib.contenttypes',
        'django.contrib.admin',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'users',
        'storages', # New
    ]
    

    Después de eso, agregue las siguientes configuraciones en su settings.py:

    AWS_ACCESS_KEY_ID = your_access_key_id
    AWS_SECRET_ACCESS_KEY = your_secret_access_key
    AWS_STORAGE_BUCKET_NAME = 'sibtc-static'
    AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
    AWS_S3_OBJECT_PARAMETERS = {
        'CacheControl': 'max-age=86400',
    }
    AWS_LOCATION = 'static'
      
    STATIC_URL = 'https://%s/%s/' % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION)
    STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
    

    Finalmente, corre python manage.py collectstatic y habrá terminado de configurar Amazon S3 para sus archivos estáticos.

    Entrega de archivos estáticos con WhiteNoise

    Las personas a menudo no usan servicios en la nube de terceros como Amazon S3 por un par de razones, incluidas las suscripciones pagas. WhiteNoise permite que su proyecto Django sirva sus propios archivos estáticos, lo que lo convierte en una unidad autónoma que podemos implementar en cualquier lugar sin depender de los proveedores de servicios.

    Aunque funciona con cualquier aplicación web compatible con WSGI, se configura más fácilmente con un proyecto de Django.

    Configuración para WhiteNoise

    Vamos a instalar Ruido blanco con:

    $ pip install whitenoise
    

    En tus settings.py, agregue WhiteNoise al MIDDLEWARE lista en el siguiente orden:

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        # WhiteNoise Middleware above all but below Security
        'whitenoise.middleware.WhiteNoiseMiddleware', 
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
      ]
    

    Para utilizar el soporte de compresión y los archivos que se pueden almacenar en caché para siempre, agregue esto en su settings.py
    STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

    correr python manage.py collectstatic.

    ¡Eso es! Ahora puede implementar su aplicación web en cualquier plataforma de alojamiento, como Heroku.

    Conclusión

    Todo desarrollador de sitios web necesita archivos estáticos para crear un sitio web atractivo y funcional. Django no solo ofrece una configuración sencilla de archivos estáticos, sino también una enorme flexibilidad para jugar con su implementación.

    En este artículo, cubrimos varias formas de integrar archivos estáticos en una aplicación web Django tanto en el desarrollo local como en la producción.

     

    Etiquetas:

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *