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 ...
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()
.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 anulados:
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ás 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. Anule 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"]