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:
Su sistema de almacenamiento personalizado debe heredar de
django.core.files.storage.Storage:from django.core.files.storage import Storage class MyStorage(Storage): ...
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 ...
Your storage class must implement the
_open()and_save()methods, along with any other methods appropriate to your storage class. See below for more on these methods.Adicionalmente, si su clase proporciona almacenamiento local de archivos, debe redefinir el método
path().Your storage class must be deconstructible so it can be serialized when it’s used on a field in a migration. As long as your field has arguments that are themselves serializable, you can use the
django.utils.deconstruct.deconstructibleclass decorator for this (that’s what Django uses on FileSystemStorage).
Por defecto, los siguientes métodos generan NotImplementedError y normalmente tienen que ser redefinidos:
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¶
El primer paso para usar un almacenamiento personalizado es indicarle a Django el backend de almacenamientos de archivo que se usará. Esto se hace a través del parámetro STORAGES de la configuración. Este parámetro mapea los aliases del almacenamiento, que es una forma de relacionar un almacenamiento específico dentro de Django a un diccionario de configuraciones para el backend de almacenamiento específico. Los parámetros para dicho diccionario están descritos en su totalidad en la documentación STORAGES
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"]