# documentación de Django - 5.1.7

# Cómo escribir una clase de almacenamiento personalizada

Si necesita proporcionar un almacenamiento de archivos personalizado -un ejemplo común es almacenar archivos en algún sistema de archivos remoto- puede hacerlo definiendo una clase de almacenamiento personalizada. Deberá seguir estos pasos:

1. Su sistema de almacenamiento personalizado debe heredar de `django.core.files.storage.Storage`:

       from django.core.files.storage import Storage

       class MyStorage(Storage): ...

2. Django debe ser capaz de crear una instancia de tu sistema de almacenamiento sin pasarle argumentos. Esto significa que cualquier ajuste debe ser tomado de `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
               ...

3. La clase de almacenamiento deberá implementar los métodos `_open()` y `_save()`, junto con cualquier otro método apropiado para tu clase de almacenamiento. Consulte a continuación para obtener más información sobre estos métodos.

   Adicionalmente, si su clase proporciona almacenamiento local de archivos, debe redefinir el método `path()`.

4. La clase de almacenamiento debe ser deconstruible para que pueda ser serializada al usarse en un campo en una migración. Siempre y cuando el campo tenga argumentos que sean serializables por sí mismos, puedes usar el decorador de clase `django.utils.deconstruct.deconstructible` con este propósito (es lo que Django usa en FileSystemStorage).

Por defecto, los siguientes métodos generan `NotImplementedError` y normalmente tienen que ser redefinidos:

- `Storage.delete()`

- `Storage.exists()`

- `Storage.listdir()`

- `Storage.size()`

- `Storage.url()`

Nóte sin embargo que no todos estos métodos son requeridos y pueden ser omitidos. Como suele ocurrir, es posible dejar cada método sin ser implementado y tener un Storage funcional.

A modo de ejemplo, si listar los contenidos de ciertos backends de almacenamiento se vuelve costoso, puedes decidir no implementar `` Storage.listdir () “”.

Otro ejemplo sería un backend que solo contemple la escritura de archivos. En este caso, no necesitaría implementar ninguno de los métodos de arriba.

Por último, la implementación de estos métodos depende de usted. Dejar algunos métodos sin implementar darían una interfaz (posiblemente rota) parcial.

Por lo general, también querrá utilizar hooks diseñados específicamente para objetos de almacenamiento personalizado. Estos son:

_open(name, mode='rb')

Requerido

Llamado por `Storage.open()`, este es el verdadero mecanismo que utiliza la clase de almacenamiento para abrir el archivo. Esto debería retornar un objeto `File`, aunque en la mayoría de casos, querrás retornar alguna subclases aquí que implemente una lógica específica para el sistema de almacenamiento backend. La excepción `FileNotFoundError` debería generarse cuando un archivo no existe.

_save(name, content)

Llamado por `Storage.save()`. El `name` ya habrá pasado por `get_valid_name()` y `get_available_name()`, y el content` será un objeto `File` por sí mismo.

Debe devolver el nombre real del archivo guardado (generalmente el `nombre` ingresado, pero si el almacenamiento necesita cambiar el nombre del archivo, devuelve el nuevo nombre).

get_valid_name(name)

Devuelve un nombre de archivo adecuado para su uso con el sistema de almacenamiento subyacente. El argumento `name` pasado a este método es el nombre de archivo original enviado al servidor o, si `upload_to` es invocable, el nombre de archivo devuelto por ese método después de eliminar cualquier información de ruta. Redefina esto para personalizar cómo se convierten los caracteres no estándar en nombres de archivos seguros.

El código proporcionado en `Storage` conserva sólo caracteres alfanuméricos, puntos y guiones bajos del nombre de archivo original, eliminando todo lo demás.

get_alternative_name(file_root, file_ext)

Devuelve un nombre de archivo alternativo basado en los parámetros `file_root` y `file_ext`. De forma predeterminada, se agrega un guión bajo más una cadena alfanumérica aleatoria de 7 caracteres al nombre del archivo antes de la extensión.

get_available_name(name, max_length=None)

Devuelve un nombre de archivo que está disponible en el mecanismo de almacenamiento, posiblemente teniendo en cuenta el nombre de archivo proporcionado. El argumento `name` pasado a este método ya se habrá limpiado a un nombre de archivo válido para el sistema de almacenamiento, de acuerdo con el método `get_valid_name()` descrito anteriormente.

La longitud del nombre del archivo no excederá `max_length`, si se proporciona. Si no se puede encontrar un nombre de archivo único y disponible, se genera una excepción `SuspiciousFileOperation`.

Si ya existe un archivo con `nombre`, se llama a `get_alternative_name()` para obtener un nombre alternativo.

## Utilice su motor de almacenamiento personalizado

The first step to using your custom storage with Django is to tell Django about the file storage backend you’ll be using. This is done using the `STORAGES` setting. This setting maps storage aliases, which are a way to refer to a specific storage throughout Django, to a dictionary of settings for that specific storage backend. The settings in the inner dictionaries are described fully in the `STORAGES` documentation.

Storages are then accessed by alias from the `django.core.files.storage.storages` dictionary:

    from django.core.files.storage import storages

    example_storage = storages["example"]