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 tramite Storage.open()
, questo è il meccanismo attuale che la casse di storage usa per aprire il file. Questo deve ritornare un oggetto File
, anche se nella maggior parte dei casi, vorrai ritornare qualche sottoclasse che implementa una logica specifica al sistema di storage di backend.
-
_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
.
Deve restituire il nome reale del file salvato (di solito il name
utilizzato in chiamata, ma se la memoria di massa deve cambiare il nome del file, il nome restituito deve essere 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