Django文件存储 默认存储系统解析


Posted in Python onAugust 02, 2019

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参数,修改创建文件的权限。

Python 相关文章推荐
python使用urlparse分析网址中域名的方法
Apr 15 Python
Python中字典和集合学习小结
Jul 07 Python
python写一个md5解密器示例
Feb 23 Python
PyQt5笔记之弹出窗口大全
Jun 20 Python
django之从html页面表单获取输入的数据实例
Mar 16 Python
Python 改变数组类型为uint8的实现
Apr 09 Python
python matplotlib.pyplot.plot()参数用法
Apr 14 Python
用Python进行websocket接口测试
Oct 16 Python
Python图像识别+KNN求解数独的实现
Nov 13 Python
python 发送邮件的四种方法汇总
Dec 02 Python
用Python提取PDF表格的方法
Apr 11 Python
python基础之停用词过滤详解
Apr 21 Python
Django 迁移、操作数据库的方法
Aug 02 #Python
Django用户认证系统 组与权限解析
Aug 02 #Python
python3中eval函数用法使用简介
Aug 02 #Python
Django用户认证系统 Web请求中的认证解析
Aug 02 #Python
Django用户认证系统 User对象解析
Aug 02 #Python
浅谈python3中input输入的使用
Aug 02 #Python
Pycharm连接远程服务器并实现远程调试的实现
Aug 02 #Python
You might like
咖啡历史、消费和行业趋势
2021/03/03 咖啡文化
phpmyadmin config.inc.php配置示例
2013/08/27 PHP
PHP输入输出流学习笔记
2015/05/12 PHP
分享50个提高PHP执行效率的技巧
2015/12/26 PHP
yii2中LinkPager增加总页数和总记录数的实例
2017/08/28 PHP
javascript vvorld 在线加密破解方法
2008/11/13 Javascript
javascript 伪数组实现方法
2010/10/11 Javascript
jquery获取iframe中的dom对象(两种方法)
2013/07/02 Javascript
jQuery让控件左右移动的三种实现方法
2013/09/08 Javascript
jquery中实现时间戳与日期相互转换
2016/04/12 Javascript
Bootstrap模仿起筷首页效果
2016/05/09 Javascript
详解vue-validator(vue验证器)
2017/01/16 Javascript
如何理解Vue的render函数的具体用法
2017/08/30 Javascript
基于vue的换肤功能的示例代码
2017/10/10 Javascript
JavaScript使用ul中li标签实现删除效果
2019/04/15 Javascript
vue+eslint+vscode配置教程
2019/08/09 Javascript
讲解Python的Scrapy爬虫框架使用代理进行采集的方法
2016/02/18 Python
PyQt 线程类 QThread使用详解
2017/07/16 Python
Python处理CSV与List的转换方法
2018/04/19 Python
Python使用lambda抛出异常实现方法解析
2020/08/20 Python
Anaconda使用IDLE的实现示例
2020/09/23 Python
CSS3中的clip-path使用攻略
2015/08/03 HTML / CSS
html5 自定义播放器核心代码
2013/12/20 HTML / CSS
全球性的奢侈品梦工厂:Forzieri(福喜利)
2019/02/20 全球购物
Nayomi官网:沙特阿拉伯王国睡衣和内衣品牌
2020/12/19 全球购物
出纳岗位职责范本
2013/12/01 职场文书
三年大学自我鉴定
2014/01/16 职场文书
小学生期末自我鉴定
2014/01/19 职场文书
乡村文明行动实施方案
2014/03/29 职场文书
医院信息公开实施方案
2014/05/09 职场文书
护士节演讲稿开场白
2014/08/25 职场文书
祖国在我心中演讲稿600字
2014/09/23 职场文书
乡镇党员干部四风对照检查材料思想汇报
2014/09/27 职场文书
幼师大班个人总结
2015/02/13 职场文书
2015年保险公司工作总结
2015/04/24 职场文书
Java多条件判断场景中规则执行器的设计
2021/06/26 Java/Android