Как создать пользовательский класс хранилища
Если вам нужно предоставить пользовательское хранилище файлов — распространённый пример — хранение файлов на какой-либо удалённой системе — вы можете сделать это, определив пользовательский класс хранилища. Вам нужно выполнить следующие шаги:
-
Ваша пользовательская система хранения должна быть подклассом
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(). - Ваш класс хранилища должен быть разъёмным, чтобы его можно было сериализовать, когда он используется в поле в миграции. Пока у вашего поля есть аргументы, которые сами по себе сериализуемы, вы можете использовать декоратор класса
django.utils.deconstruct.deconstructibleдля этого (Django использует его для FileSystemStorage).
По умолчанию следующие методы вызывают 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"]
© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/5.1/howto/custom-file-storage/