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

New in Django 4.2.

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 from the django.core.files.storage.storages dictionary:

from django.core.files.storage import storages

example_storage = storages["example"]
Back to Top