Come scrivere una storage class personalizzata¶
Se necessiti di utilizzare un file storage personalizzato – un esempio comune è salvare files su un sistema remoto – puoi farlo definendo una classe di storage personalizzata. Dovrai seguire i seguenti passi:
Il tuo sistema di storage personalizzato deve essere una sottoclasse di
django.core.files.storage.Storage
:from django.core.files.storage import Storage class MyStorage(Storage): ...
Django deve essere in grado di istanziare il tuo sistema di storage senza nessun argomento. Ciò significa che qualsiasi impostazione deve essere reperita da
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 tua classe di storage deve implementare i metodi
_open()
e_save()
, insieme ad ogni altro metodo appropriato per la tua classe di storage. Vedi di seguito per sapere di più su questi metodi.In aggiunta, se la tua classe fornisce un file storage locale, deve sovrascrivere il metodo
path()
.La tua classe di storage deve essere deconstructible così che possa essere serializzata quando è utilizzata in un campo all’interno di una migrazione. Fintanto che i tuoi campi hanno argomenti che sono essi stessi serializable, puoi usare il class decorator
django.utils.deconstruct.deconstructible
(è ciò che usa Django nel FileSystemStorage).
Di default, i metodi seguenti sollevano un «NotImplementedError» e devono essere sovrascritti.
Nota comunque che non tutti questi metodi sono necessari a posso essere deliberatamente omessi. Come succede, è possibile lasciare tutti i metodi non implementati e avere uno Storage funzionante.
A titolo di esempio, se fare la lista dei contenuti di alcuni backend di storage risulta dispendioso, potresti decidere di non implementare Storage.listdir()
.
Un altro esempio potrebbe essere un backend che scrive solamente su file. In questo caso potrebbe non essere necessario implementare nessuno dei metodi sopracitati.
In ultimo, l’implementazione di questi metodi dipende da te. Lasciare alcuni metodi non implementati risulterà in un’interfaccia parziale (probabilmente non funzionante).
Generalmente vorrai anche usare un hook disegnato appositamente per gli oggetti del custom storage. Questi sono:
- _open(name, mode='rb')¶
Richiesto.
Chiamato da Storage.open()
, questo è il meccanismo effettivo utilizzato dalla classe di archiviazione per aprire il file. Questo deve restituire un oggetto File
, anche se nella maggior parte dei casi vorrai restituire qui qualche sottoclasse che implementa la logica specifica del sistema di archiviazione backend. L’eccezione FileNotFoundError
dovrebbe essere sollevata quando un file non esiste.
- _save(name, content)¶
Chiamato da Storage.save()
. name
sarà già passato attraverso get_valid_name()
e get_available_name()
, e content
sarà un oggetto File
.
Dovrebbe restituire il nome effettivo del file salvato (di solito il nome
passato, ma se l’archivio deve modificare il nome del file, restituire invece il nuovo nome).
- get_valid_name(name)¶
Restituisce un nome di file idoneo all’uso con il sottostante sistema di memorizzazione. L’argomento name
passato a questo metodo o è il nome del file inviato al server o, se upload_to
è un metodo richiamabile, è il nome del file restituito da quel metodo dopo avere rimosso ogni informazione sul path. Effettua l’override di questo per personalizzare il modo di convertire i caratteri non-standard in nomi di file sicuri.
Il codice fornito in Storage
conserva dai nomi originali dei file solo i caratteri alfanumerici, i punti e i trattini bassi, rimuovendo qualunque altra cosa.
- get_alternative_name(file_root, file_ext)¶
Restituisce un nome del file alternativo basato sui parametrio file_root
e file_ext
. Di default, al nome del file viene appesa una stringa con un underscore e 7 caratteri casuali, prima dell’estensione.
- get_available_name(name, max_length=None)¶
Restituisce un nome di file che sia disponibile nel sistema di memorizzazione, possibilmente prendendo in considerazione il nome del file fornito. L’argomento name
passato a questo metodo dovrà essere già trasformato per essere un nome di file valido per il sistema di memorizzazione, in accordo al metodo get_valid_name()
descritto precedentemente.
La lunghezza del nome del file non supererà max_length
, se indicata. Se non sarà trovato un nome di file univoco libero, verrà sollevata una eccezione SuspiciousFileOperation
.
se un file con «nome» esiste già, viene chiamato «get_alternative_name()» per ottenere un nome alternativo
Utilizza il tuo motore di archiviazione personalizzato¶
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"]