Spec-Zone.ru › Django 4.1

Как написать пользовательский класс хранилища

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

  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/4.1/howto/custom-file-storage/

Spec-Zone.ru

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