# Django 5.2.8 ドキュメント

# カスタムのストレージクラスを書く

たとえばリモートシステム上にファイルを保存する場合、カスタムストレージクラスを定義することで、カスタムファイルストレージを作成することが可能です。使用するには以下の手順に従ってください。

1. カスタムストレージシステムは `django.core.files.storage.Storage` のサブクラスでなければなりません。

       from django.core.files.storage import Storage

       class MyStorage(Storage): ...

2. Django は引数なしでストレージシステムをインスタンス化できなければなりません。これは、次のように `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.

   さらにカスタムクラスがローカルファイルストレージを提供する場合は、 `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).

デフォルトにおいて、以下に示すメソッドは `NotImplementedError` を発生させます。したがって一般的にオーバーライドする必要があります。

- `Storage.delete()`

- `Storage.exists()`

- `Storage.listdir()`

- `Storage.size()`

- `Storage.url()`

ただし上のメソッドはすべてが必要というわけでもないため、意図的に省略することもできます。もし例外が発生してもそのメソッドを未実装のままにしておくことも可能であり、それでもストレージを動作させることはできます。

特定のストレージバックエンドにおける内容一覧の取得には相当な手間がかかる、ということがわかったとします。その場合は `Storage.listdir()` の実装をしなくても構いません。

バックエンドとして、単にファイル出力だけを扱うものであったとします。この場合は、上のメソッドをすべて実装する必要がありません。

結局、上のメソッドを実装するかどうかは開発者次第です。メソッドのどれかを未実装のままにしておくというのは、一部分のみの (場合によっては壊れたままの) インターフェースとするということです。

カスタムストレージオブジェクトに固有のフックメソッドを用意することもあるでしょう。以下があります。

_open(name, mode='rb')

必須

`Storage.open()` から呼び出されます。このストレージクラスにとって、ファイルを開くために実際に用いられる機能となります。バックエンドストレージシステムに固有のロジックを実装して、特定サブクラスのオブジェクトを戻り値としたい場合も多くありますが、このメソッドは必ず `File` オブジェクトを戻り値としなければなりません。ファイルが存在しない場合は、 `FileNotFoundError` 例外が発生します。

_save(name, content)

`Storage.save()` から呼び出されます。`name` は `get_valid_name()` や `get_available_name()` を通じて得られたものであり、`content` は `File` オブジェクトそのものです。

戻り値は、実際に保存されたファイルの名前です (通常は処理された `name` ですが、ストレージがファイル名を変更する必要がある場合には、新たな名前を返す必要があります)。

get_valid_name(name)

ベースとなるストレージシステムで使用するのに適したファイル名を返します。このメソッドに渡される `name` 引数は、サーバに送信された元のファイル名か、 `upload_to` が呼び出し可能オブジェクトの場合、そのメソッドがパス情報を削除した後に返すファイル名です。非標準文字を安全なファイル名に変換する方法をカスタマイズするには、これをオーバーライドします。

`Storage` において実装されているコードにおいては、元々のファイル名の中から、アルファベット、数字、ピリオド、アンダースコアのみが保持され、それ以外は取り除かれます。

get_alternative_name(file_root, file_ext)

"file_root"と"file_ext"のパラメーターを基に新たなファイルネームを返します。デフォルトでは、ファイルネームの拡張子の前にアンダーバーとランダムな7文字の英数字の文字列を加えます。

get_available_name(name, max_length=None)

ストレージシステムにおいて利用可能なファイル名を返します。これは指定されたファイル名をできるかぎり考慮に入れた名称です。本メソッドに受け渡される `name` 引数は、上に示した `get_valid_name()` メソッドを用いて、ストレージシステムが扱うファイル名として正常化されたものにします。

`max_length` を指定した場合、ファイル名の長さはそれを越えないようにします。適切に一致するファイル名が見つからなかった場合は、例外 `SuspiciousFileOperation` が発生します。

`name` というファイルが既に存在する場合、 `get_alternative_name()` が代わりの名前を得るために呼び出されます。

## カスタムのストレージエンジンを使用する

Django でカスタムストレージを使うための最初のステップは、利用するファイルストレージバックエンドを Django に伝えることです。これは `STORAGES` 設定で行います。この設定は、Django を通して特定のストレージを参照するためのエイリアスを、ストレージバックエンドを定義する辞書にマッピングします。この辞書の内部的な設定については、 `STORAGES` ドキュメントで詳しく説明しています。

ストレージには、エイリアスである `django.core.files.storage.storages` 辞書からアクセスできます:

    from django.core.files.storage import storages

    example_storage = storages["example"]