如何编写自定义存储类¶
如果你需要提供自定义文件存储(一个常见的示例是在某些远程系统上存储文件),你可以通过定义一个自定义存储类来实现。你需要遵循以下步骤
你的自定义存储系统必须是
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
(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_root
和 file_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"]