目錄
如果你需要提供自定義文件儲存功能——一個常用的場景是,把文件儲存在遠程系統中——自定義一個存儲類可以完成這一任務來完成。下面是需要完成的具體步驟:
自定義存儲系統的步驟
1. 繼承Storage
你自定義的存儲系統必須爲 django.core.files.storage.Storage的一個子類:
from django.core.files.storage import Storage
class MyStorage(Storage):
...
2. 設置文件中配置參數
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
...
3.實現特定方法
在你的存儲類中,除了其他自定義的方法外,還必須實現 _open()
以及 _save()
方法。關於這些方法,詳情請查看下面的信息。
另外,如果你的類提供了本地文件存儲,它必須重載 path() 方法。
4. deconstructible
您的存儲類必須是deconstructible,以便在遷移中的字段上使用它時可以序列化。 只要你的字段有自己的參數可以自動序列化,你可以使用django.utils.deconstruct.deconstructible類裝飾器(這是Django在FileSystemStorage上使用的)。
@deconstructible
class FileSystemStorage(Storage):
"""
Standard filesystem storage
"""
5. 其他可選項
默認情況,下面的方法會引發一個 NotImplementedError,通常需要重寫。
Storage.delete()
Storage.exists()
Storage.listdir()
Storage.size()
Storage.url()
然而並非所有方法都是需要的,並且可能故意被省略。
舉例來說,如果列出某些存儲後端的內容會比較消耗性能,那麼您可以決定不實現Storage.listdir
方法。
另一個例子是隻處理寫入文件的後端。在這種情況下,你不需要實現上述任何方法。
最終,你決定實現這些方法中的一些。另一些未實現的方法會生成部分(可能會損壞的)接口。
你可能也經常會用到專爲自定義存儲對象設計的 鉤子函數。他們是:
_open(name, mode=‘rb’)
必須重寫(因爲父類沒有實現).
它將被Storage.open()
調用,這纔是存儲類用來打開文件的真正機制,這個方法必須要返回一個文件對象。儘管在大多數時候,你想要這個方法返回一個繼承於特定邏輯的後臺存儲系統的子類。
_save(name, content)
它將被Storage.save()
調用。這個 name 早已經過get_valid_name()
和 get_available_name()
,並且 content 將會成是 File
對象自身。
應該返回保存的文件名的實際名稱(通常是傳入“name”,但如果內存需要改變文件名,則返回新名稱)。
get_valid_name(name)
返回適用於底層存儲系統的文件名。 傳遞給此方法的name
參數既不是發送給服務器的原始文件名也不是upload_to
(upload_to
是可調用的),則在刪除任何路徑信息後由該方法返回的文件名。 重寫此操作可以自定義如何將非標準字符轉換爲安全文件名。
“Storage”上提供的代碼僅保留原始文件名中的字母數字字符,句點和下劃線,並刪除其他所有內容。
get_available_name(name, max_length=None)
返回存儲機制中可用的文件名,可能會考慮提供的文件名。 根據上述get_valid_name()
方法,傳遞給此方法的name
參數已經被處理爲一個對存儲系統有效的文件名。
返回的文件名的長度不會超過max_length
,如果該參數被提供的話。若找不到一個可用的獨一無二的文件名,則拋出一個SuspiciousFileOperation 異常。
如果已經存在一個 name 的文件,則會在擴展後綴前添加下劃線和7位隨機字母。