# Documentation Django 5.2.8

# Écriture d’une classe de stockage personnalisée

Si vous avez besoin de fournir un stockage de fichiers personnalisé, typiquement pour stocker des fichiers dans un système distant, vous pouvez le faire en définissant une classe de stockage personnalisée. Il faudra suivre ces étapes :

1. Votre système de stockage personnalisé doit être une sous-classe de `django.core.files.storage.Storage`:

       from django.core.files.storage import Storage

       class MyStorage(Storage): ...

2. Django doit être capable d’instancier votre système de stockage sans paramètre. Cela signifie que tout réglage doit provenir 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
               ...

3. Your storage class must implement the `_open()` and `_save()` methods, along with any other methods appropriate to your storage class. See below for more on these methods.

   De plus, si votre classe propose du stockage de fichiers locaux, elle doit surcharger la méthode `path()`.

4. Your storage class must be deconstructible so it can be serialized when it’s used on a field in a migration. As long as your field has arguments that are themselves serializable, you can use the `django.utils.deconstruct.deconstructible` class decorator for this (that’s what Django uses on FileSystemStorage).

Par défaut, les méthodes suivantes génèrent `NotImplementedError` et doivent typiquement être surchargées :

- `Storage.delete()`

- `Storage.exists()`

- `Storage.listdir()`

- `Storage.size()`

- `Storage.url()`

Notez cependant que ces méthodes ne sont pas toutes obligatoires et peuvent être délibérément omises. Il est même possible d’obtenir une classe de stockage fonctionnelle sans implémenter aucune de ces méthodes.

À titre d’exemple, si l’énumération du contenu de certains moteurs de stockage se révèle coûteuse, il est tout à fait possible de décider de ne pas implémenter `Storage.listdir()`.

Un autre exemple pourrait être un moteur qui ne gère que l’écriture dans des fichiers. Dans ce cas, il ne serait pas nécessaire d’implémenter une seule des méthodes ci-dessus.

Au final, le choix des méthodes à implémenter vous revient. En laissant certaines méthodes non implémentées, l’interface proposée sera partielle (voire défectueuse).

Il est généralement souhaitable d’implémenter les méthodes tout spécialement conçues pour les objets de stockage personnalisé. Ce sont :

_open(name, mode='rb')

Obligatoire.

Appelée par `Storage.open()`, c’est le mécanisme utilisé par la classe de stockage pour ouvrir un fichier. Elle doit renvoyer un objet `File`, même si dans la plupart des cas, elle renverra plutôt une sous-classe qui implémente la logique particulière du moteur de stockage. C’est l’exception `FileNotFoundError` qui doit être générée lorsqu’un fichier n’existe pas.

_save(name, content)

Appelée par `Storage.save()`. Le paramètre `name` aura déjà passé par `get_valid_name()` et `get_available_name()`, et `content` sera un objet de type `File`.

Elle doit renvoyer le nom réel du fichier enregistré (normalement le paramètre `name`, mais si le stockage a besoin de modifier le nom de fichier, c’est le nouveau nom qui devra être renvoyé).

get_valid_name(name)

Renvoie un nom de fichier acceptable par le système de stockage sous-jacent. Le paramètre `name` passé à cette méthode est soit le nom de fichier original envoyé au serveur, soit, si `upload_to` est exécutable, le nom de fichier renvoyé par cette méthode dépourvu de toute notion de chemin. Surchargez cette méthode pour personnaliser la manière dont des caractères non standards sont convertis pour former des noms de fichiers sûrs.

Le code fourni par `Storage` ne conserve que les caractères alphanumériques, les points et les soulignements du nom de fichier original, supprimant tout le reste.

get_alternative_name(file_root, file_ext)

Renvoie un nom de fichier différent basé sur les paramètres `file_root` et `file_ext`. Par défaut, un soulignement suivi d’une chaîne aléatoire de 7 caractères alphanumériques sont ajoutés à la fin du nom du fichier avant l’extension.

get_available_name(name, max_length=None)

Renvoie un nom de fichier disponible (non existant) dans le mécanisme de stockage, prenant potentiellement en compte le nom de fichier fourni. Le paramètre `name` transmis à cette méthode aura déjà été nettoyé afin d’être un nom de fichier valable pour le système de stockage, en accord avec la méthode `get_valid_name()` décrite ci-dessus.

La longueur du nom de fichier ne dépassera pas `max_length`, si cette option est indiquée. Si un nom de fichier unique n’est pas disponible, une exception `SuspiciousFileOperation` est générée.

Si un fichier avec `name` existe déjà, `get_alternative_name()` est appelée pour obtenir un nom différent.

## Utiliser son propre moteur de stockage personnalisé

La première chose à faire lorsqu’on veut utiliser son propre stockage avec Django est de le renseigner au sujet du moteur de stockage que vous souhaitez utiliser. Cela se fait au niveau du réglage `STORAGES`. Ce réglage fait correspondre des alias de stockage, qui sont une manière de se référer à des stockages spécifiques dans le code de Django, à un dictionnaire de réglages pour le moteur de stockage concerné. Les réglages du dictionnaire interne sont détaillés dans la documentation de `STORAGES`.

On peut ensuite accéder aux stockages par leur alias à partir du dictionnaire data:django.core.files.storage.storages:

    from django.core.files.storage import storages

    example_storage = storages["example"]