estaticos carga archivos django amazon-s3 django-settings static-files django-storage

carga - static css django



¿Cómo configurar un proyecto de Django con django-storage y Amazon S3, pero con diferentes carpetas para archivos estáticos y archivos multimedia? (4)

Archivo: PROJECT_NAME / custom_storages.py

from django.conf import settings from storages.backends.s3boto import S3BotoStorage class StaticStorage(S3BotoStorage): location = settings.STATICFILES_LOCATION class MediaStorage(S3BotoStorage): location = settings.MEDIAFILES_LOCATION

Archivo: PROJECT_NAME / settings.py

STATICFILES_LOCATION = ''static'' MEDIAFILES_LOCATION = ''media'' if not DEBUG: STATICFILES_STORAGE = ''PROJECT_NAME.custom_storages.StaticStorage'' DEFAULT_FILE_STORAGE = ''PROJECT_NAME.custom_storages.MediaStorage'' AWS_ACCESS_KEY_ID = ''KEY_XXXXXXX'' AWS_SECRET_ACCESS_KEY = ''SECRET_XXXXXXXXX'' AWS_STORAGE_BUCKET_NAME = ''BUCKET_NAME'' AWS_HEADERS = {''Cache-Control'': ''max-age=86400'',} AWS_QUERYSTRING_AUTH = False

Y ejecute: python manage.py collectstatic

Estoy configurando un proyecto de Django que usaba el sistema de archivos del servidor para almacenar los archivos estáticos de las aplicaciones ( STATIC_ROOT ) y los archivos cargados por el usuario ( MEDIA_ROOT ).

Ahora necesito alojar todo ese contenido en el S3 de Amazon, así que he creado un cubo para esto. Utilizando django-storages storage con el back-end de almacenamiento de boto , logré subir statics recopilados al bucket S3:

MEDIA_ROOT = ''/media/'' STATIC_ROOT = ''/static/'' DEFAULT_FILE_STORAGE = ''storages.backends.s3boto.S3BotoStorage'' AWS_ACCESS_KEY_ID = ''KEY_ID...'' AWS_SECRET_ACCESS_KEY = ''ACCESS_KEY...'' AWS_STORAGE_BUCKET_NAME = ''bucket-name'' STATICFILES_STORAGE = ''storages.backends.s3boto.S3BotoStorage''

Luego, tengo un problema: el MEDIA_ROOT y el STATIC_ROOT no se utilizan dentro del depósito, por lo que la raíz del depósito contiene tanto los archivos estáticos como las rutas cargadas por el usuario.

Entonces podría establecer:

S3_URL = ''http://s3.amazonaws.com/%s'' % AWS_STORAGE_BUCKET_NAME STATIC_URL = S3_URL + STATIC_ROOT MEDIA_URL = ''S3_URL + MEDIA_ROOT

Y use esas configuraciones en las plantillas, pero no hay distinción de archivos estáticos / multimedia cuando se almacena en S3 con django-storages .

¿Cómo se puede hacer esto?

¡Gracias!


Actualmente estoy usando este código en un módulo s3utils separado:

from django.core.exceptions import SuspiciousOperation from django.utils.encoding import force_unicode from storages.backends.s3boto import S3BotoStorage def safe_join(base, *paths): """ A version of django.utils._os.safe_join for S3 paths. Joins one or more path components to the base path component intelligently. Returns a normalized version of the final path. The final path must be located inside of the base path component (otherwise a ValueError is raised). Paths outside the base path indicate a possible security sensitive operation. """ from urlparse import urljoin base_path = force_unicode(base) paths = map(lambda p: force_unicode(p), paths) final_path = urljoin(base_path + ("/" if not base_path.endswith("/") else ""), *paths) # Ensure final_path starts with base_path and that the next character after # the final path is ''/'' (or nothing, in which case final_path must be # equal to base_path). base_path_len = len(base_path) - 1 if not final_path.startswith(base_path) / or final_path[base_path_len:base_path_len + 1] not in ('''', ''/''): raise ValueError(''the joined path is located outside of the base path'' '' component'') return final_path class StaticRootS3BotoStorage(S3BotoStorage): def __init__(self, *args, **kwargs): super(StaticRootS3BotoStorage, self).__init__(*args, **kwargs) self.location = kwargs.get(''location'', '''') self.location = ''static/'' + self.location.lstrip(''/'') def _normalize_name(self, name): try: return safe_join(self.location, name).lstrip(''/'') except ValueError: raise SuspiciousOperation("Attempted access to ''%s'' denied." % name) class MediaRootS3BotoStorage(S3BotoStorage): def __init__(self, *args, **kwargs): super(MediaRootS3BotoStorage, self).__init__(*args, **kwargs) self.location = kwargs.get(''location'', '''') self.location = ''media/'' + self.location.lstrip(''/'') def _normalize_name(self, name): try: return safe_join(self.location, name).lstrip(''/'') except ValueError: raise SuspiciousOperation("Attempted access to ''%s'' denied." % name)

Luego, en mi módulo de configuración:

DEFAULT_FILE_STORAGE = ''myproyect.s3utils.MediaRootS3BotoStorage'' STATICFILES_STORAGE = ''myproyect.s3utils.StaticRootS3BotoStorage''

Tengo que redefinir el método privado _normalize_name() para usar una versión "fija" de la función safe_join() , ya que el código original me está dando excepciones de safe_join() SuspiciousOperation para rutas legales.

Estoy publicando esto para consideración, si alguien puede dar una mejor respuesta o mejorar esta, será muy bienvenido.


Creo que la respuesta es bastante simple y está hecha por defecto. Esto me funciona en AWS Elastic Beanstalk con Django 1.6.5 y Boto 2.28.0:

STATICFILES_FINDERS = ( ''django.contrib.staticfiles.finders.FileSystemFinder'', ''django.contrib.staticfiles.finders.AppDirectoriesFinder'', ) TEMPLATE_LOADERS = ( ''django.template.loaders.filesystem.Loader'', ''django.template.loaders.app_directories.Loader'', ) DEFAULT_FILE_STORAGE = ''storages.backends.s3boto.S3BotoStorage'' STATICFILES_STORAGE = ''storages.backends.s3boto.S3BotoStorage'' AWS_ACCESS_KEY_ID = os.environ[''AWS_ACCESS_KEY_ID''] AWS_SECRET_ACCESS_KEY = os.environ[''AWS_SECRET_KEY'']

Las claves AWS se transfieren desde el archivo de configuración del contenedor y no tengo STATIC_ROOT ningún STATIC_ROOT o STATIC_URL . Además, no es necesario el archivo s3utils.py . Estos detalles son manejados por el sistema de almacenamiento de forma automática. El truco aquí es que necesitaba hacer referencia a esta ruta desconocida en mis plantillas de forma correcta y dinámica. Por ejemplo:

<link rel="icon" href="{% static "img/favicon.ico" %}">

Así es como me dirijo a mi favicon que vive localmente (previo al despliegue) en ~/Projects/my_app/project/my_app/static/img/favicon.ico .

Por supuesto, tengo un archivo local_settings.py separado para acceder a este material localmente en el entorno de desarrollo y tiene las configuraciones ESTÁTICA y MEDIA. Tuve que experimentar y leer mucho para encontrar esta solución y funciona de manera consistente sin errores.

Entiendo que necesita la separación estática y de raíz, y teniendo en cuenta que solo puede proporcionar un depósito, señalaría que este método toma todas las carpetas de mi entorno local en ~/Projects/my_app/project/my_app/static/ y crea un carpeta en la raíz del contenedor (es decir: S3bucket / img / como en el ejemplo anterior). Entonces consigues separación de archivos. Por ejemplo, podría tener una carpeta de media en la carpeta static y acceder a ella a través de plantillas con esto:

{% static "media/" %}

Espero que esto ayude. Vine aquí buscando la respuesta y presioné un poco más para encontrar una solución más simple que extender el sistema de almacenamiento. En su lugar, leí la documentación sobre el uso previsto de Boto y descubrí que gran parte de lo que necesitaba estaba incorporado de manera predeterminada. ¡Aclamaciones!


Creo que lo siguiente debería funcionar y ser más simple que el método de Mandx, aunque es muy similar:

Crea un archivo s3utils.py :

from storages.backends.s3boto import S3BotoStorage StaticRootS3BotoStorage = lambda: S3BotoStorage(location=''static'') MediaRootS3BotoStorage = lambda: S3BotoStorage(location=''media'')

Luego en su settings.py :

DEFAULT_FILE_STORAGE = ''myproject.s3utils.MediaRootS3BotoStorage'' STATICFILES_STORAGE = ''myproject.s3utils.StaticRootS3BotoStorage''

Un ejemplo diferente pero relacionado (que en realidad he probado) se puede ver en los dos archivos example_ here .