カスタムのストレージクラスを書く¶
たとえばリモートシステム上にファイルを保存する場合、カスタムストレージクラスを定義することで、カスタムファイルストレージを作成することが可能です。使用するには以下の手順に従ってください。
カスタムストレージシステムは
django.core.files.storage.Storage
のサブクラスでなければなりません。from django.core.files.storage import Storage class MyStorage(Storage): ...
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 ...
カスタムストレージクラスには
_open()
と_save()
メソッドが必要です。さらにストレージに必要なメソッドが他にもあれば定義します。こういったメソッドに関しては以降を参照してください。さらにカスタムクラスがローカルファイルストレージを提供する場合は、
path()
メソッドをオーバーライドする必要があります。ストレージクラスは deconstructible でなければならないので、マイグレーションのフィールドで使われたときにそれはシリアライズすることができます。フィールドがそれ自身 serializable である引数を持つ限り、これのために
django.utils.deconstruct.deconstructible
クラスデコレータを使うことができます (それが FileSystemStorage で Django が使うものです)。
デフォルトにおいて、以下に示すメソッドは NotImplementedError
を発生させます。したがって一般的にオーバーライドする必要があります。
ただし上のメソッドはすべてが必要というわけでもないため、意図的に省略することもできます。もし例外が発生してもそのメソッドを未実装のままにしておくことも可能であり、それでもストレージを動作させることはできます。
特定のストレージバックエンドにおける内容一覧の取得には相当な手間がかかる、ということがわかったとします。その場合は 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"]