Spec-Zone.ru › Django 1.8

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

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

  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 , переданный в этот метод, — это исходное имя файла после удаления любой информации о пути. Переопределите этот метод, чтобы настроить преобразование нестандартных символов в безопасные имена файлов.

Представленный на Storage код сохраняет только буквенно-цифровые символы, точки и подчёркивания из исходного имени файла, удаляя всё остальное.

get_available_name(name, max_length=None)

Возвращает имя файла, доступное в механизме хранения, возможно, с учётом переданного имени файла. Аргумент name , переданный в этот метод, уже очищен до имени файла, пригодного для системы хранения, в соответствии с методом get_valid_name() , описанным выше.

Длина имени файла не будет превышать max_length, если предоставлено. Если свободный уникальный файл не может быть найден, возникает исключение SuspiciousFileOperation.

Если файл с name уже существует, к имени файла перед расширением добавляется знак подчёркивания и случайная 7-символьная буквенно-цифровая строка.

Ранее к имени файла добавлялся знак подчёркивания, за которым следовали цифры (например, "_1", "_2", и т. д.) до тех пор, пока не находилось доступное имя в целевом каталоге. Злоумышленник мог использовать этот детерминированный алгоритм для создания атаки с отказом в обслуживании. Это изменение также было внесено в Django 1.6.6, 1.5.9 и 1.4.14.

Аргумент max_length был добавлен.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/1.8/howto/custom-file-storage/

Spec-Zone.ru

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