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:

  1. 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):
        ...
    
  2. 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
            ...
    
  3. 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().

  4. 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

Back to Top