Django預設使用的檔案儲存系統 您所在的位置:网站首页 0o666 Django預設使用的檔案儲存系統

Django預設使用的檔案儲存系統

2022-11-24 05:54| 来源: 网络整理| 查看: 265

Django預設使用的檔案儲存系統’django.core.files.storage.FileSystemStorage’是一個本地儲存系統,由settings中的DEFAULT_FILE_STORAGE值確定。 class FileSystemStorage(location=None, base_url=None, file_permissions_mode=None, directory_permissions_mode=None) FileSystemStorage類繼承自Storage類,location是儲存檔案的絕對路徑,預設值是settings中的MEDIA_ROOT值,base_url預設值是settings中的MEDIA_URL值。 當定義location引數時,可以無視MEDIA_ROOT值來儲存檔案:

from django.db import models from django.core.files.storage import FileSystemStorage fs = FileSystemStorage(location='/media/photos') class Car(models.Model): ... photo = models.ImageField(storage=fs)

這樣檔案會儲存在/media/photos資料夾。 可以直接使用Django的檔案儲存系統來儲存檔案:

>>> from django.core.files.storage import default_storage >>> from django.core.files.base import ContentFile >>> path = default_storage.save('/path/to/file', ContentFile('new content')) >>> path '/path/to/file' >>> default_storage.size(path) 11 >>> default_storage.open(path).read() 'new content' >>> default_storage.delete(path) >>> default_storage.exists(path) False 可以從FileSystemStorage類的_save方法看下上傳檔案是怎麼儲存的: def _save(self, name, content): full_path = self.path(name) # Create any intermediate directories that do not exist. # Note that there is a race between os.path.exists and os.makedirs: # if os.makedirs fails with EEXIST, the directory was created # concurrently, and we can continue normally. Refs #16082. directory = os.path.dirname(full_path) if not os.path.exists(directory): try: if self.directory_permissions_mode is not None: # os.makedirs applies the global umask, so we reset it, # for consistency with file_permissions_mode behavior. old_umask = os.umask(0) try: os.makedirs(directory, self.directory_permissions_mode) finally: os.umask(old_umask) else: os.makedirs(directory) except OSError as e: if e.errno != errno.EEXIST: raise if not os.path.isdir(directory): raise IOError("%s exists and is not a directory." % directory) # There's a potential race condition between get_available_name and # saving the file; it's possible that two threads might return the # same name, at which point all sorts of fun happens. So we need to # try to create the file, but if it already exists we have to go back # to get_available_name() and try again. while True: try: # This file has a file path that we can move. if hasattr(content, 'temporary_file_path'): file_move_safe(content.temporary_file_path(), full_path) # This is a normal uploadedfile that we can stream. else: # This fun binary flag incantation makes os.open throw an # OSError if the file already exists before we open it. flags = (os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, 'O_BINARY', 0)) # The current umask value is masked out by os.open! fd = os.open(full_path, flags, 0o666) _file = None try: locks.lock(fd, locks.LOCK_EX) for chunk in content.chunks(): if _file is None: mode = 'wb' if isinstance(chunk, bytes) else 'wt' _file = os.fdopen(fd, mode) _file.write(chunk) finally: locks.unlock(fd) if _file is not None: _file.close() else: os.close(fd) except OSError as e: if e.errno == errno.EEXIST: # Ooops, the file exists. We need a new file name. name = self.get_available_name(name) full_path = self.path(name) else: raise else: # OK, the file save worked. Break out of the loop. break if self.file_permissions_mode is not None: os.chmod(full_path, self.file_permissions_mode) # Store filenames with forward slashes, even on Windows. return force_text(name.replace('\\', '/'))

方法中可以看出,先判斷檔案儲存的目錄是否存在,如果不存在,使用os.mkdirs()依次建立目錄。 根據directory_permissions_mode引數來確定建立的目錄的許可權,應該為(0777 &~umask)。 然後使用os.open()建立檔案,flags引數為(os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, ‘O_BINARY’, 0)), 這樣當檔案已存在時,則報EEXIST異常,使用get_available_name()方法重新確定檔案的名字。 mode為0o666,許可權為(0666 &~umask)。 content為FILE物件,如一切正常,使用FILE.chunks()依次將內容寫入檔案。 最後,根據file_permissions_mode引數,修改建立檔案的許可權。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有