Si necesita proporcionar un almacenamiento de archivos personalizado – un ejemplo común es almacenar archivos en algún sistema remoto – puede hacerlo definiendo una clase de almacenamiento personalizada. Deberá seguir estos pasos:
Su sistema de almacenamiento personalizado debe ser una subclase de django.core.files.storage.Storage:
from django.core.files.storage import Storage
class MyStorage(Storage): ...
Django debe poder instanciar su sistema de almacenamiento sin argumentos. Esto significa que cualquier configuración se debe tomar desde django.conf.settings:
from django.conf import settings
from django.core.files.storage import Storage
class MyStorage(Storage):
def __init__(self, option=None):
if not option:
option = settings.CUSTOM_STORAGE_OPTIONS
...
Tu almacenamiento debe implementar los métodos _open() y _save(), junto con cualquier otro método apropiado para tu clase de almacenamiento. Consulte a continuación más información sobre estos métodos.
Además, si tu clase proporciona almacenamiento en archivos locales, debe sobrescribir el método path().
Tu clase de almacenamiento debe ser deconstructible para que pueda serializarse cuando se utiliza en un campo de una migración. A medida que tu campo tenga argumentos que sean ellos mismos serializable, puedes utilizar el decorador django.utils.deconstruct.deconstructible para esto (ese es lo que Django utiliza en FileSystemStorage).
Por defecto, los siguientes métodos levantan una NotImplementedError y suelen tener que ser sobrescritos:
Sin embargo, no todos estos métodos son necesarios y pueden ser deliberadamente omitidos. Como sucede, es posible dejar cada método sin implementar y aún así tener un almacenamiento funcional.
Por ejemplo, si la lista de contenidos de ciertos backends de almacenamiento resulta ser costosa, podrías decidir no implementar Storage.listdir().
Otro ejemplo podría ser un backend que solo maneje escrituras a archivos. En este caso, no necesitarías implementar ninguno de los métodos anteriores.
Finalmente, qué métodos se implementan es cosa tuya. Dejar algunos métodos sin implementar dará como resultado una interfaz parcial (posiblemente rota).
También sueles querer utilizar ganchos específicamente diseñados para objetos de almacenamiento personalizados. Estos son:
Requerido.
Llamado por Storage.open(), este es el mecanismo real que la clase de almacenamiento utiliza para abrir el archivo. Debe devolver un objeto File, aunque en la mayoría de los casos, quieres devolver alguna subclase aquí que implemente lógica específica del sistema de almacenamiento backend. Se debe levantar la excepción FileNotFoundError cuando no exista el archivo.
Llamado por Storage.save(). El name ya habrá pasado por get_valid_name() y get_available_name(), y el content será un objeto File en sí mismo.
Debería devolver el nombre real del archivo guardado (generalmente el name pasado, pero si el almacenamiento necesita cambiar el nombre del archivo devuelve el nuevo nombre en su lugar).
Devuelve un nombre de archivo adecuado para usar con el sistema de almacenamiento subyacente. El argumento name pasado a este método es ya sea el nombre original enviado al servidor o, si upload_to es una función, el nombre del archivo devuelto por esa función después de eliminar cualquier información de ruta. Sobrescribe esto para personalizar cómo se convierten los caracteres no estándar a nombres de archivos seguros.
El código proporcionado en Storage retiene solo caracteres alfa-numéricos, puntos y guiones bajos del nombre original del archivo, eliminando todo lo demás.
Returns an alternative filename based on los parámetros file_root y file_ext. Por defecto, se agrega un guión bajo más una cadena alfanumérica de 7 caracteres aleatorios antes de la extensión.
Returns a filename that is available in the storage mechanism, possibly taking into account el nombre proporcionado. El argumento name pasado a este método ya habrá sido limpiado a un nombre válido para el sistema de almacenamiento, según el método get_valid_name() descrito anteriormente.
La longitud del nombre del archivo no superará max_length, si se proporciona. Si no se puede encontrar un nombre de archivo único disponible, se levanta una excepción SuspiciousFileOperation.
Si el archivo con el nombre name ya existe, se llama a get_alternative_name() para obtener un nombre alternativo.
El primer paso para utilizar su motor de almacenamiento personalizado con Django es informarle a Django sobre el backend de almacenamiento de archivos que utilizará. Esto se hace utilizando la configuración STORAGES. Esta configuración mapea alias de almacenamiento, que son una forma de referirse a un almacenamiento específico en todo Django, a un diccionario de configuraciones para ese almacenamiento backend específico. Las configuraciones en los diccionarios internos se describen completamente en la documentación STORAGES.
Los almacenamientos luego se acceden por alias desde el diccionario django.core.files.storage.storages:
from django.core.files.storage import storages
example_storage = storages["example"]
may 31, 2026