Django實現靜態文件緩存到雲服務的操作方法
一般與頁面有關的系統都會有大量的靜態文件,包括js、css以及圖標圖片等,這些文件一般是項目的相對路徑,在加載的時候會從本地讀取再轉發出去。由於這類文件一般比較大,導致接口響應變長,但是這些文件一般很少改動,所以非常適合通過Nginx或者雲服務來緩存。一般雲服務與cdn無縫集成,能夠更快下發到客戶端。我們後臺系統很多使用的是基於python的Django框架,該怎麼來實現靜態文件緩存呢?
這個過程簡單的讓人驚訝,但是開始一直搞不清楚關系,前前後後耽誤瞭不少時間。
1.collectstatic命令
首先 Django有一個collectstatic的命令,該腳本的功能是將本地的靜態文件以及需要的依賴,例如Django和python自己需要的靜態文件等打包到一個統一的目錄下。這有點類似於maven發佈前的打包功能。
這個腳本一般在上線的時候會執行。例如我們的啟動腳本裡這麼寫的:
sh collectstatic.sh
然後在djang的配置文件裡加這麼一行:
static-map = /static=./static_files
我們將本地的靜態文件打包發送到雲服務就是用collectstatic來實現的。
2.如何發佈到雲服務
方法非常簡單,代碼也非常少,但是貌似很多地方都沒說清楚為什麼,害的我搞瞭好久,白瞭很多垃圾代碼。
首先你要新建一個繼承瞭Storage的類,例如這樣子:
@deconstructible class CosStorage(Storage):
上面的註解也必須要有的。
然後在很多材料裡會將,要在這裡類裡實現多個方法,有的是以_開頭,有的就是普通的類,我理解_開頭的主要是collectstatic執行的方法,而不帶的是程序執行的時候調用的。前者類似java中的各類service,程序啟動的時候就會執行。而後者類似controller下的接口,隻有外部調用的時候才會執行。
以_開頭的方法最重要的是下面這三個:
def __init__(self): logging.info('init cos file list...') self.get_cos_file_list() # 看看這裡是否需要 def _open(self, name, mode='r'): return File(open(self.path(name), mode)) def _save(self, name, content): cms.util.upload_os_file(FileBizType.TRUMAN_CMS_STATIC_FILES, content, name, name) time.sleep(0.02)
__init__自然是為瞭初始化而設置的。根據需要寫對應的代碼,例如調用雲服務需要的簽名等等
_open()這個我當時忘瞭測試一下有沒有用瞭,按道理這裡是打開文件的,反正我是上麼這麼寫的。
_save(self, name, content)是最關鍵的代碼。這個接口是理解Storage的兩大鑰匙。這個方法的功能是處理當前已經打開的文件,文件標題就是name,content就是將文件內容轉換成的字節流,你直接用就行。這個該怎麼理解呢?
name的含義:假如你的靜態路徑很深,文件很多,類型也很雜。那麼Storage首先就幫你處理路徑的問題瞭,name就是相對路徑+文件名。所以你傳的時候使用name就將相對目錄一起傳過去瞭。
content的含義:content就是文件的內容,不管是js、css、還是圖標圖片,在網絡傳的時候都會先轉換成字節流是不是。這裡的content就是當前文件的字節流。所以就使用upload_os_file(content) 就將文件內容發出去瞭,不需要自己再讀文件 ,轉換成字節流等操作。不過這裡的upload_os_file是我自己的業務代碼,你可以根據需要做對應的實現。
另外一個重要的問題是_save一次隻處理一個文件,所以你寫這個方法裡的代碼的時候隻要考瞭一個文件就行瞭,不用多此一舉寫批量等邏輯。
這裡還有一點就是如果不加限制,_save的執行速度會非常快 ,一下就將所有文件全部讀到,並且一個文件一個請求全部發出去,這可能導致服務端來不及處理而被拒絕等情況。方法也很簡單,_save裡加個等待就行瞭
time.sleep(0.02)
上面的代碼在服務啟動過程中執行到collectstatic時會自動掃描,自動加載,自動執行,但是你要在自己的配置文件中添加如下信息,否則會找不到。
STATICFILES_STORAGE = 'cos.cos_storage.CosStorage'
3.訪問時是如何重定向到cos的
將文件存到雲服務之後,頁面執行的時候怎麼訪問呢?
這就涉及到Storage的其他幾個方法瞭,主要是:
def listdir(self, path): pass def delete(self, name): pass def size(self, name): pass def url(self, name): url = cms.util.get_file_os_download_url(name) return url def exists(self, name): pass
上面看名字我們就能大致知道功能,最重要的是url()方法,這個是理解Storage的第二把鑰匙。
這裡的name就是文件在雲服務中的相對路徑,你需要將拼接一下你的域名等就是文件的地址瞭。然後返回就行瞭。
如果靜態文件都是公開的,這裡的url貌似不寫也行,能夠自動實現將域名和文件相對路徑拼接程完整的訪問url。
但是在我們的系統中,靜態文件是不允許直接訪問,需要帶簽名的。 所以我們這裡需要在url裡通過自定義的get_file_os_download_url()方法去訪問我們另外一個服務。
但是這裡有一個坑,就是python的基礎包中也會用相對路徑訪問自己的靜態文件,也就是這麼寫”/title.png”等,這種情況無法被url攔截到。因為我們業務的代碼裡是統一加前綴/static/的。
該怎麼攔截,至今沒有解決,如果你知道,請和我說,謝謝!
到此這篇關於Django實現靜態文件緩存到雲服務的操作方法的文章就介紹到這瞭,更多相關Django靜態文件緩存內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Django實現文件分享系統的完整代碼
- Python Django搭建文件下載服務器的實現
- Django的基本運用之Django垃圾分類詳解
- Django上傳xlsx文件直接轉化為DataFrame或直接保存的方法
- python爬取一組小姐姐圖片實例