编写自定义存储系统

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

  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在FileSystemStorage上使用的)。

默认情况下,以下方法引发NotImplementedError,通常必须被覆盖:

但请注意,并不是所有这些方法都是必需的,可能会被故意忽略。 发生这种情况时,可能会使每种方法都未实现,并且仍然有一个可用的存储空间。

举例来说,如果列出某些存储后端的内容变得昂贵,则可能决定不执行Storage.listdir

另一个例子是只处理写入文件的后端。 在这种情况下,您不需要实现上述任何方法。

最终,这些方法中的哪一个是由您决定的。 留下一些方法未实现将导致一个部分(可能会损坏)的接口。

您通常也会使用专门为自定义存储对象设计的挂钩。 这些是:

_opennamemode ='rb'

必需 T0>。

Storage.open()调用,这是存储类用于打开文件的实际机制。 这必须返回一个File对象,尽管在大多数情况下,您会希望返回一些子类来实现特定于后端存储系统的逻辑。

_savenamecontent

Storage.save()调用。 The name will already have gone through get_valid_name() and get_available_name(), and the content will be a File object itself.

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

get_valid_name T0>(名称 T1>)¶ T2>

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

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

get_available_namenamemax_length = None

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

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

如果name的文件已经存在,则在扩展名之前的文件名后面加下划线加一个随机的7个字符的字母数字字符串。