zoukankan      html  css  js  c++  java
  • Django文件存储(一)默认存储系统

    Django默认使用的文件存储系统'django.core.files.storage.FileSystemStorage'是一个本地存储系统,由settings中的DEFAULT_FILE_STORAGE值确定。

    class FileSystemStorage(location=Nonebase_url=Nonefile_permissions_mode=Nonedirectory_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参数,修改创建文件的权限。

  • 相关阅读:
    数据预处理和特征工程
    批量梯度下降,随机梯度下降,小批量梯度下降
    动态规划和贪心算法的区别
    广告计价方式:CPM,CPC,CPA
    隐语义模型LFM
    windows下安装xgboost
    KMP算法
    sklearn中的SGDClassifier
    JS变量和数据类型
    JS的基本使用 使用外部的JS文件
  • 原文地址:https://www.cnblogs.com/linxiyue/p/7442232.html
Copyright © 2011-2022 走看看