如果你需要提供自定義文件存儲 – 一個普遍的例子是在某個遠(yuǎn)程系統(tǒng)上儲存文件 – 你可以通過定義一個自定義的儲存類來實現(xiàn)。你需要遵循以下步驟:
1. 你的自定義儲存類必須是django.core.files.storage.Storage的子類:
from django.core.files.storage import Storage
class MyStorage(Storage):
...
2. Django必須能夠不帶任何參數(shù)來實例化你的儲存類。這意味著任何設(shè)置都應(yīng)該從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. 你的儲存類必須實現(xiàn) _open() 和 _save()方法,以及任何適合于你的儲存類的其它方法。更多這類方法請見下文。
另外,如果你的類提供本地文件存儲,它必須覆寫path()方法。
4. 你的儲存類必須是 可以析構(gòu)的,所以它在遷移中的一個字段上使用的時候可以被序列化。只要你的字段擁有自己可以序列化的參數(shù),你就可以為它使用django.utils.deconstruct.deconstructible類裝飾器(這也是Django用在FileSystemStorage上的東西)。
默認(rèn)情況下,下面的方法會拋出NotImplementedError異常,并且必須覆寫它們。
然而要注意,并不是這些方法全部都需要,可以故意省略一些??梢圆槐貙崿F(xiàn)每個方法而仍然能擁有一個可以工作的儲存類。
比如,如果在特定的儲存后端中,列出內(nèi)容的開銷比較大,你可以決定不實現(xiàn)Storage.listdir。
另一個例子是只處理寫入文件的后端。這種情況下,你不需要實現(xiàn)上面的任意一種方法。
根本上來說,需要實現(xiàn)哪種方法取決于你。如果不去實現(xiàn)一些方法,你會得到一個不完整(可能是不能用的)的接口。
你也會經(jīng)常想要使用特意為自定義儲存對象設(shè)計的鉤子。它們是:
_open(name, mode='rb')
必需的。
被Storage.open()調(diào)用,這是儲存類用于打開文件的實際工具。它必須返回File對象,在大多數(shù)情況下,你會想要返回一些子類,它們實現(xiàn)了后端儲存系統(tǒng)特定的邏輯。
_save(name, content)
被Storage.save()調(diào)用。name必須事先通過get_valid_name() 和 get_available_name()過濾,并且content自己必須是一個File對象。
應(yīng)該返回被保存文件的真實名稱(通常是傳進來的name,但是如果儲存需要修改文件名稱,則返回新的名稱來代替)。
get_valid_name(name)
返回適用于當(dāng)前儲存系統(tǒng)的文件名。傳遞給該方法的name參數(shù)是發(fā)送給服務(wù)器的原始文件名稱,并移除了所有目錄信息。你可以覆寫這個方法,來自定義非標(biāo)準(zhǔn)的字符將會如何轉(zhuǎn)換為安全的文件名稱。
Storage提供的代碼只會保留原始文件名中的數(shù)字和字母字符、英文句號和下劃線,并移除其它字符。
get_available_name(name, max_length=None)
返回在儲存系統(tǒng)中可用的文件名稱,可能會顧及到提供的文件名稱。傳給這個方法的name參數(shù)需要事先過濾為儲存系統(tǒng)有效的文件名稱,根據(jù)上面描述的get_valid_name() 方法。
如果提供了max_length,文件名稱長度不會超過它。如果不能找到可用的、唯一的文件名稱,會拋出SuspiciousFileOperation 異常。
如果name命名的文件已存在,一個下劃線加上隨機7個數(shù)字或字母的字符串會添加到文件名稱的末尾,擴展名之前。
Changed in Django 1.7:
之前,下劃線和一位數(shù)字(比如"_1", "_2",以及其他)會添加到文件名稱的末尾,直到目標(biāo)目錄中發(fā)現(xiàn)了可用的名稱。一些惡意的用戶會利用這一確定性的算法來進行dos攻擊。 這一變化也在1.6.6, 1.5.9, 和 1.4.14中出現(xiàn)。
Changed in Django 1.8:
新增了max_length參數(shù)。
自定義儲存系統(tǒng) 以相同方式工作:你可以把它們作為storage參數(shù)傳遞給FileField。
譯者:Django 文檔協(xié)作翻譯小組,原文:Custom storage。
本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請保留作者署名和文章出處。
Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。