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

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

  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. カスタムストレージクラスには _open()_save() メソッドが必要です。さらにストレージに必要なメソッドが他にもあれば定義します。こういったメソッドに関しては以降を参照してください。

    さらにカスタムクラスがローカルファイルストレージを提供する場合は、 path() メソッドをオーバーライドする必要があります。

  4. ストレージクラスは deconstructible でなければならないので、マイグレーションのフィールドで使われたときにそれはシリアライズすることができます。フィールドがそれ自身 serializable である引数を持つ限り、これのために django.utils.deconstruct.deconstructible クラスデコレータを使うことができます (それが FileSystemStorage で Django が使うものです)。

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

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

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

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

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

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

_open(name, mode='rb')

必須

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

_save(name, content)

Storage.save() から呼び出されます。nameget_valid_name()get_available_name() を通じて得られたものであり、contentFile オブジェクトそのものです。

戻り値は、実際に保存されたファイルの名前です (通常は処理された 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"]
Back to Top