O django é um framework para desenvolvimento web na linguagem Python e seu funcionamento é, majoritariamente, baseado em alguns padrões de design, como, por exemplo, os decorators e adapters. O sistema de storage de arquivos de mídia e de arquivos estáticos funciona, de modo simples, seguindo o padrão adapter.
Arquivos de Mídia são os arquivos enviados pelos usuários por meio dos campos de upload de arquivo (
ImageField
eFileField
).Arquivos Estáticos são os arquivos para serem usados nos layouts (como, por exemplo, scripts, styles e assets).
O django-storages
é uma biblioteca que fornece alguns adapters para o sistema de armazenamento do django, enviando arquivos para provedores de nuvem, como a AWS (Amazon Web Service) e a GCP (Google Cloud Platform).
O problema
Utilizando o sistema original de armazenamento, em disco, do django para arquivos estáticos e para arquivos de mídia ao mesmo tempo existem alguns comportamentos que são padrão e que acabam passando sem serem notados:
Durante o upload de arquivos (FileField
ou ImageField
) quando enviamos dois arquivos com o mesmo nome, por padrão, o adapter de storage adiciona uma parte aleatória no fim do nome do arquivo, permitindo, dessa forma, o upload de ambos sem conflitarem.
Já os arquivos estáticos, aqueles que são "coletados" utilizando o comando python manage.py collectstatic
, os conflitos de nomes são resolvidos de uma forma diferente: "o arquivo que for localizado primeiro em uma das localizações especificadas será utilizado" (Ver Referência [1]).
Essa diferença entre os comportamentos, configurações padrões para ambos os adapters, é de suma importância pois, não faz sentido adicionar um jquery_xyz.js
, por exemplo, a cada vez que o comando python manage.py collectstatic
for executado.
django-storages e a unificação do comportamento
O django-storages, mais especificamente seus adapters S3Boto3Storage
e S3StaticStorage
, unifica esses dois comportamentos em uma configuração AWS_S3_FILE_OVERWRITE
que por padrão é True
e de acordo com [2], "por padrão, arquivos com o mesmo nome serão sobrescritos um ao outro. Mude para False
para adicionar caracteres extra adicionados".
O problema ainda persiste, pois o comportamento precisa ser diferente para cada um dos adapter. A solução é não alterar a propriedade AWS_S3_FILE_OVERWRITE
e sobrescrever o adapter de upload de arquivos de mídia definindo essa configuração localmente:
# core/storages.py
from storages.backends.s3boto3 import S3Boto3Storage
class MediaS3Boto3Storage(S3Boto3Storage):
file_overwrite = False
Assim, alterando no settings.py
a configuração principal:
DEFAULT_FILE_STORAGE = 'core.storages.MediaS3Boto3Storage'
No exemplo, abaixo, o mesmo arquivo foi enviado duas vezes para o bucket S3 e o segundo aparece já com os caracteres acrescentados ao fim do nome:
Observações
Segundo o comentário em [3], não existe a necessidade em, de fato, substituir o adapter e a configuração AWS_S3_FILE_OVERWRITE = False
poderia ser utilizada devido ao fato de que o django remove o arquivo antes de criar o novo ao executar o comando python manage.py collectstatic
, porém essa é uma questão não confirmada e que, além disso, deixa preocupações, por exemplo, em futuras atualizações do próprio django.
Referências
[1] The staticfiles app - Django Documentation.
[2] Amazon S3 - Django-storages Documentation.
[3] jschneier on GitHub.
Top comments (0)