Skip to main content

编写自定义存储系统

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

  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 对象,但在大多数情况下,您将需要返回一些子类,实现专用于后端存储系统的逻辑。

_save(name, content)

Storage.save() 调用。 name 将已经经历了 get_valid_name()get_available_name(),并且 content 将是 File 对象本身。

应该返回保存的文件的名称的实际名称(通常是 name 传入的,但是如果存储需要更改文件名,则返回新名称)。

get_valid_name(name)

返回适用于底层存储系统的文件名。传递给此方法的 name 参数是发送到服务器的原始文件名,或者如果 upload_to 是可调用的,则在删除任何路径信息后,由该方法返回的文件名。覆盖此选项以自定义非标准字符如何转换为安全文件名。

Changed in Django 1.9:

在旧版本中,当 upload_to 是可调用的时,不调用此方法。

Storage 上提供的代码仅保留原始文件名中的字母数字字符,句点和下划线,并删除其他所有字符。

get_available_name(name, max_length=None)

返回在存储机制中可用的文件名,可能会考虑提供的文件名。根据上述 get_valid_name() 方法,传递给此方法的 name 参数已经被清除为对存储系统有效的文件名。

文件名的长度不会超过 max_length (如果提供)。如果找不到自由唯一文件名,则会引发 SuspiciousFileOperation 异常。

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