编写一个自定义存储系统
如果你需要提供自定义文件储存功能——一个普通的例子是,把文件储存在远程系统中——自定义一个存储类可以完成这一任务来完成。下面是需要完成的具体步骤:
- 你自定义的存储系统必须为
Django.core.files.storage.Storage
:: 的一个子类。
- from django.core.files.storage import Storage
- class MyStorage(Storage):
- ...
- Django必须能以无参数实例化你的存储系统。意味着所有设置都应从
dango.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
- ...
另外,如果你的类提供了本地文件存储,它必须重载 path()
方法。
- 您的存储类必须是:ref:deconstructible,以便在迁移中的字段上使用它时可以序列化。 只要你的字段有自己的参数:ref:serializable,你可以使用django.utils.deconstruct.deconstructible类装饰器(这是Django在FileSystemStorage上使用的)
通常,下面的方法会引发一个 NotImplementedError,并通常必须被重写。
Storage.delete()
Storage.exists()
Storage.listdir()
Storage.size()
Storage.url()
可是,记住并非所有这些方法都是需要的,并且可能故意被省略。正因为如此,让每个方法未实现并仍然拥有一个可用储存是可能的。
举例来说,如果列出某些存储后端的内容会比较消耗性能,那么您可以决定不实现Storage.listdir
方法。
另一个例子是只处理写入文件的后端。在这种情况下,你不需要实现上述任何方法。
最终,你决定实现这些方法中的哪一个。一些方法未实现结果会生成部分(可能会损坏的)接口。
你可能也经常会用到专为自定义存储对象设计的钩子函数。他们是:
使用“Storage.open()”方法才是存储类用来打开文件的真正机制,这个方法必须要返回一个文件对象。尽管在大多数时候,你想要这个方法返回一个继承于特定逻辑的后台存储系统的子类。
save
(_name, content)- 被称为
Storage.save()
。这个name
会早已经历get_valid_name()
和get_available_name()
,并且content
将会成为 ``File``对象自身。
应该返回保存的文件名的实际名称(通常是传入“name”,但如果内存需要改变文件名,则返回新名称)。
getvalid_name
(_name)- 返回适用于底层存储系统的文件名。 传递给此方法的
name
参数既不是发送给服务器的原始文件名,如果upload_to
是可调用的,则在删除任何路径信息后由该方法返回的文件名。 重写此操作可以自定义如何将非标准字符转换为安全文件名。
“Storage”上提供的代码仅保留原始文件名中的字母数字字符,句点和下划线,并删除其他所有内容。
getavailable_name
(_name, max_length=None)- Returns a filename that is available in the storage mechanism, possibly takingthe provided filename into account. The
name
argument passed to this methodwill have already cleaned to a filename valid for the storage system, accordingto theget_valid_name()
method described above.
The length of the filename will not exceed max_length
, if provided. If afree unique filename cannot be found, a SuspiciousFileOperation
exception is raised.
如果已经存在一个 name
的文件,则会在扩展后缀前添加下划线和7位随机字母。