如何编写自定义存储类

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

  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.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_rootfile_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"]
返回顶部