https://docs.djangoproject.com/en/3.1/topics/files/
自定义存储;
编写自定义存储系统¶
如果需要提供自定义文件存储(一个常见的示例是在某个远程系统上存储文件),则可以通过定义自定义存储类来实现。您需要按照以下步骤操作:
-
您的自定义存储系统必须是的子类
django.core.files.storage.Storage
:from django.core.files.storage import Storage class MyStorage(Storage): ...
-
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 ...
-
您的存储类必须实现
_open()
和_save()
方法,以及适用于您的存储类的任何其他方法。有关这些方法的更多信息,请参见下文。另外,如果您的类提供本地文件存储,则它必须重写该
path()
方法。 -
您的存储类必须是可分解的, 以便在迁移中的字段上使用时可以序列化。只要您的字段具有本身可序列化的参数,就 可以
django.utils.deconstruct.deconstructible
为此使用类装饰器(Django在FileSystemStorage上使用的 装饰器)。
默认情况下,以下方法会引发NotImplementedError
,通常将被覆盖:
但是请注意,并非所有这些方法都是必需的,因此可以有意省略。碰巧的是,有可能使每个方法都未实现,而仍然可以使用存储。
举例来说,如果列出某些存储后端的内容确实很昂贵,则可以决定不实施Storage.listdir()
。
另一个示例是仅处理写入文件的后端。在这种情况下,您将不需要实现任何上述方法。
最终,由您决定采用哪种方法。保留一些未实现的方法将导致部分(可能已损坏)接口。
您通常还需要使用专门为自定义存储对象设计的挂钩。这些是:
_open
(名称,mode ='rb')¶
必填项。
由调用Storage.open()
,这是存储类用于打开文件的实际机制。这必须返回一个File
对象,尽管在大多数情况下,您将需要在此处返回一些实现特定于后端存储系统的逻辑的子类。
_save
(名称,内容)¶
由呼叫Storage.save()
。该name
会已经走过 get_valid_name()
和get_available_name()
,而content
将是一个 File
对象本身。
应该返回保存的文件名的实际名称(通常是name
传入的名称,但是如果存储需要更改文件名,请返回新名称)。
get_valid_name
(名称)¶
返回适合与基础存储系统一起使用的文件名。name
传递给此方法的 参数是发送到服务器的原始文件名,或者是(如果upload_to
是可调用的)在删除任何路径信息之后该方法返回的文件名。覆盖此选项可自定义如何将非标准字符转换为安全文件名。
提供的代码Storage
仅保留原始文件名中的字母数字字符,句点和下划线,并删除所有其他内容。
get_alternative_name
(file_root,file_ext)¶
根据file_root
和file_ext
参数返回备用文件名。默认情况下,在扩展名之前,在文件名后附加一个下划线和一个随机的7个字符的字母数字字符串。
get_available_name
(名称,max_length = None)¶
返回存储机制中可用的文件名,可能考虑了提供的文件名。根据name
上述方法,传递给此方法的参数将已经清除为对存储系统有效的文件名get_valid_name()
。
文件名的长度将不超过max_length
(如果提供)。如果找不到免费的唯一文件名,SuspiciousFileOperation
则会引发异常。
如果文件name
已经存在,get_alternative_name()
则被调用以获得备用名称。