Spec-Zone.ru › Django 3.2

Написание пользовательской системы хранения

Если вам необходимо предоставить пользовательское хранилище файлов — распространённый пример — хранение файлов на какой-либо удалённой системе — вы можете сделать это, определив пользовательский класс хранилища. Вам необходимо выполнить следующие шаги:

  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. Ваш класс хранилища должен быть разъёмным, чтобы его можно было сериализовать при использовании в поле в миграции. Пока ваши аргументы поля сами являются сериализуемыми, вы можете использовать декоратор класса django.utils.deconstruct.deconstructible для этого (Django использует его для FileSystemStorage).

По умолчанию следующие методы вызывают NotImplementedError и обычно должны быть переопределены:

  • Storage.delete()
  • Storage.exists()
  • Storage.listdir()
  • Storage.size()
  • Storage.url()

Однако не все эти методы являются обязательными и могут быть намеренно опущены. Так случается, что можно оставить каждый метод нереализованным и при этом иметь работающее хранилище.

Например, если перечисление содержимого определённых хранилищ оказывается дорогостоящим, вы можете решить не реализовывать Storage.listdir().

Другим примером будет хранилище, которое обрабатывает только запись в файлы. В этом случае вам не нужно реализовывать ни один из вышеперечисленных методов.

В конечном счёте, реализация этих методов зависит от вас. Опускание некоторых методов приведёт к частичному (возможно, неработающему) интерфейсу.

Вы также обычно захотите использовать крючки, специально разработанные для пользовательских объектов хранения. Это:

_open(name, mode='rb')

Обязательно.

Вызывается Storage.open(), это фактический механизм, который использует класс хранилища для открытия файла. Он должен возвращать объект File, хотя в большинстве случаев вы захотите вернуть здесь какой-либо подкласс, который реализует логику, специфичную для системы хранения на бэкенде.

_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 Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/3.2/howto/custom-file-storage/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API