Django文件存储(一)默认存储系统
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参数,修改创建文件的权限。
Django文件存储(一)默认存储系统的更多相关文章
- Django文件存储(二)定制存储系统
要自己写一个存储系统,可以依照以下步骤: 1.写一个继承自django.core.files.storage.Storage的子类. from django.core.files.storage im ...
- android 开发-数据存储之文件存储
android的文件存储是通过android的文件系统对数据进行临时的保存操作,并不是持久化数据,例如网络上下载某些图片.音频.视频文件等.如缓存文件将会在清理应用缓存的时候被清除,或者是应用卸载的时 ...
- django中云存储静态文件
Django自带文件存储系统存储在本地文件夹,如果我们将文件存储在云端,需要自定义文件存储系统. 自定义文件存储系统需要继承django.core.files.storage.Storage from ...
- django 自定义存储上传文件的文件名
一.需求: Django实现自定义文件名存储文件 使文件名看起来统一 避免收到中文文件导致传输.存储等问题 相同的文件也需要使用不同的文件名 二.实现思路: 思路: 生成14位随机字母加数字.后10位 ...
- PostgreSQL的存储系统二:REDOLOG文件存储结构二
REDOLOG文件里的用户数据和数据文件里的用户数据存储结构相同 几个月前同事给台湾一家公司培训<pg9 ad admin>时,有个学员提及WAL里记录的内容为Query时的SQL语句(比 ...
- 修改Jupyter Notebook默认文件存储路径(已安装Anaconda)
https://blog.csdn.net/weixin_44799144/article/details/91823079 修改Jupyter Notebook默认文件存储路径首先,安装好Anaco ...
- 使用Docker跑MySQL 作为Django的存储后端
Docker的好处不科普了,用过的都说好. 不想污染自己开发机器上的文件环境,本萌新使用Docker运行Mysql,Redis来作为Django的存储后端和缓存. 在第一次安装过程中,我遇到了一些问题 ...
- Hadoop小文件存储方案
原文地址:https://www.cnblogs.com/ballwql/p/8944025.html HDFS总体架构 在介绍文件存储方案之前,我觉得有必要先介绍下关于HDFS存储架构方面的一些知识 ...
- (转)FastDFS文件存储
一.FastDFS介绍 FastDFS开源地址:https://github.com/happyfish100 参考:分布式文件系统FastDFS设计原理 参考:FastDFS分布式文件系统 个人封装 ...
随机推荐
- C语言结构体指针初始化(转)
reference: https://www.cnblogs.com/losesea/archive/2012/11/15/2772526.html 今天来讨论一下C中的内存管理. 记得上周在饭桌上和 ...
- python 文件读写时用open还是codecs.open
当我面有数据需要保存时,第一时间一般会想到写到一个txt文件中,当然,数据量比较大的时候还是写到数据库比较方便管理,需要进行网络传输时要序列化,json化.下面主要整理一下平时用的最多的写入到文件中, ...
- get 乱码解决方案
1.针对Post方式提交的请求如果出现乱码,可以每次在request解析数据时设置编码格式: request.setCharacterEncoding("utf-8"); 也可以使 ...
- python:3种爬虫的优缺点
性能对比 爬取方法 性 能 ...
- 剑指Offer 4. 重建二叉树 (二叉树)
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- 7--Python入门--条件和循环
5.1 条件语句 条件语句基本框架如下:if 判断语句1: 执行语句块1elif 判断语句2: 执行语句块2else: 执行语句块3 a = 10 if a%2 == 0 : #这里使用了取余函数% ...
- ASP.NET中出现内存溢出错误System.OutOfMemoryException
原因1:数据库服务器性能问题导致内存不够用,从而引起内存溢出 原因2:在IIS的应用程序池中进行配置,引起IIS服务器的内存分配问题,从而引起内存溢出 分析: 32位操作系统的寻址空间是 ...
- ie8网页时调用特定的css文件
加上条件注释语句<!--[if IE 8]><link rel="".........................><![endif]--> ...
- leetcode 846.Hand of Straights
对于一个数组中的数分为W组且在每一组内的数是连续存在的. 考虑使用map映射来记录每个数的个数的,并且对于数组中的数进行从小到大的排列的.同时每次需要更新最开始的那个起始数的,可能是以及出现的也可能是 ...
- spring中使用@PostConstruct和@PreConstruct注解
1.@PostConstruct说明 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法.被@PostCo ...