编写自定义存储系统

如果需要提供自定义文件存储(一个常见的例子是在某个远程系统上存储文件),可以通过定义自定义存储类来实现。您需要遵循以下步骤:

  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. 您的存储类必须是 deconstructible 因此,当它在迁移中的字段上使用时,可以序列化它。只要你的领域有自己的论点 serializable ,您可以使用 django.utils.deconstruct.deconstructible 类修饰器(这是Django在文件系统存储中使用的)。

默认情况下,以下方法将引发 NotImplementedError 通常必须重写:

但是请注意,并非所有这些方法都是必需的,并且可以故意省略。当它发生时,可以让每个方法保持未实现,并且仍然有一个工作存储器。

举例来说,如果列出某些存储后端的内容代价高昂,您可能会决定不实施 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_available_name(name, max_length=None)

返回存储机制中可用的文件名,可能会考虑提供的文件名。这个 name 根据 get_valid_name() 上述方法。

文件名的长度不会超过 max_length ,如果提供的话。如果找不到可用的唯一文件名,则 SuspiciousFileOperation 引发异常。

如果有文件 name 已经存在,一个下划线加上一个随机的7个字符的字母数字字符串将附加到扩展名之前的文件名中。