您的位置:1010cc时时彩经典版 > 1010cc时时彩经典版 > 【1010cc时时彩经典版】暗许存款和储蓄系统,怎

【1010cc时时彩经典版】暗许存款和储蓄系统,怎

发布时间:2019-09-01 16:55编辑:1010cc时时彩经典版浏览(156)

    Django文件存储(二)定制存款和储蓄系统,django文件存款和储蓄

    要团结写一个仓库储存系统,能够依据以下步骤:

    1.写四个继续自django.core.files.storage.Storage的子类。

    from django.core.files.storage import Storage
    
    class MyStorage(Storage):
        ...
    

    2.Django必得能够在无任何参数的景色下实例化MyStorage,所以任何条件设置必得来自django.conf.settings。

    from django.conf import settings
    from django.core.files.storage import Storage
    
    class MyStorage(Storage):
        def __init__(self, option=None):
            if not option:
                option = settings.CUSTOM_STORAGE_OPTIONS
            ...
    

    3.依据Storage的open和save方法源码:

        def open(self, name, mode='rb'):
            """
            Retrieves the specified file from storage.
            """
            return self._open(name, mode)
    
    
        def save(self, name, content, max_length=None):
            """
            Saves new content to the file specified by name. The content should be
            a proper File object or any python file-like object, ready to be read
            from the beginning.
            """
            # Get the proper name for the file, as it will actually be saved.
            if name is None:
                name = content.name
    
            if not hasattr(content, 'chunks'):
                content = File(content, name)
    
            name = self.get_available_name(name, max_length=max_length)
            return self._save(name, content)
    

    MyStorage须求完结_open和_save方法。

    要是写的是个地面存款和储蓄系统,还要重写path方法。

    4.用到django.utils.deconstruct.deconstructible装饰器,以便在migration能够体系化。

    再有,Storage.delete()、Storage.exists()、Storage.listdir()、Storage.size()、Storage.url()方法都会报NotImplementedError,也需求重写。

    要和煦写一个囤积系统,能够依据以下步骤:

    要和煦写二个囤积系统,可以服从以下步骤:

    假诺您必要提供一个自定义的文本存款和储蓄-一个大规模的例证正是在长距离系统上囤积文件-你可以经过定义三个融洽的存款和储蓄类来做这件职业,你将通过弹指间步骤:

    Django文件存款和储蓄(一)默许存款和储蓄系统,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参数,修改创设文件的权位。

    Django私下认可使用的文本存款和储蓄系统'django.core.files.storage.FileSystemStorage'是一个地面存款和储蓄系统,由...

    Django Qiniu Storage

    七牛云有和好的django storage系统,可以看下是怎么运作的,地址

    先在意况变量恐怕settings中配置QINIU_ACCESS_KEY、QINIU_SECRET_KEY、QINIU_BUCKET_NAME、QINIU_BUCKET_DOMAIN、QINIU_SECURE_URL。

    使用七牛云托管顾客上传的文书,在 settings.py 里安装DEFAULT_FILE_STORAGE:

    DEFAULT_FILE_STORAGE = 'qiniustorage.backends.QiniuStorage'
    

    动用七牛托管动态变化的公文以及站点本身的静态文件,设置:

    STATICFILES_STORAGE  = 'qiniustorage.backends.QiniuStaticStorage'
    

    运作python manage.py collectstatic,静态文件就能够被合併上传来七牛。

    QiniuStorage代码如下:

    @deconstructible
    class QiniuStorage(Storage):
        """
        Qiniu Storage Service
        """
        location = ""
    
        def __init__(
                self,
                access_key=QINIU_ACCESS_KEY,
                secret_key=QINIU_SECRET_KEY,
                bucket_name=QINIU_BUCKET_NAME,
                bucket_domain=QINIU_BUCKET_DOMAIN,
                secure_url=QINIU_SECURE_URL):
    
            self.auth = Auth(access_key, secret_key)
            self.bucket_name = bucket_name
            self.bucket_domain = bucket_domain
            self.bucket_manager = BucketManager(self.auth)
            self.secure_url = secure_url
    
        def _clean_name(self, name):
            """
            Cleans the name so that Windows style paths work
            """
            # Normalize Windows style paths
            clean_name = posixpath.normpath(name).replace('\', '/')
    
            # os.path.normpath() can strip trailing slashes so we implement
            # a workaround here.
            if name.endswith('/') and not clean_name.endswith('/'):
                # Add a trailing slash as it was stripped.
                return clean_name   '/'
            else:
                return clean_name
    
        def _normalize_name(self, name):
            """
            Normalizes the name so that paths like /path/to/ignored/../foo.txt
            work. We check to make sure that the path pointed to is not outside
            the directory specified by the LOCATION setting.
            """
    
            base_path = force_text(self.location)
            base_path = base_path.rstrip('/')
    
            final_path = urljoin(base_path.rstrip('/')   "/", name)
    
            base_path_len = len(base_path)
            if (not final_path.startswith(base_path) or
                    final_path[base_path_len:base_path_len   1] not in ('', '/')):
                raise SuspiciousOperation("Attempted access to '%s' denied." %
                                          name)
            return final_path.lstrip('/')
    
        def _open(self, name, mode='rb'):
            return QiniuFile(name, self, mode)
    
        def _save(self, name, content):
            cleaned_name = self._clean_name(name)
            name = self._normalize_name(cleaned_name)
    
            if hasattr(content, 'chunks'):
                content_str = b''.join(chunk for chunk in content.chunks())
            else:
                content_str = content.read()
    
            self._put_file(name, content_str)
            return cleaned_name
    
        def _put_file(self, name, content):
            token = self.auth.upload_token(self.bucket_name)
            ret, info = put_data(token, name, content)
            if ret is None or ret['key'] != name:
                raise QiniuError(info)
    
        def _read(self, name):
            return requests.get(self.url(name)).content
    
        def delete(self, name):
            name = self._normalize_name(self._clean_name(name))
            if six.PY2:
                name = name.encode('utf-8')
            ret, info = self.bucket_manager.delete(self.bucket_name, name)
    
            if ret is None or info.status_code == 612:
                raise QiniuError(info)
    
        def _file_stat(self, name, silent=False):
            name = self._normalize_name(self._clean_name(name))
            if six.PY2:
                name = name.encode('utf-8')
            ret, info = self.bucket_manager.stat(self.bucket_name, name)
            if ret is None and not silent:
                raise QiniuError(info)
            return ret
    
        def exists(self, name):
            stats = self._file_stat(name, silent=True)
            return True if stats else False
    
        def size(self, name):
            stats = self._file_stat(name)
            return stats['fsize']
    
        def modified_time(self, name):
            stats = self._file_stat(name)
            time_stamp = float(stats['putTime']) / 10000000
            return datetime.datetime.fromtimestamp(time_stamp)
    
        def listdir(self, name):
            name = self._normalize_name(self._clean_name(name))
            if name and not name.endswith('/'):
                name  = '/'
    
            dirlist = bucket_lister(self.bucket_manager, self.bucket_name,
                                    prefix=name)
            files = []
            dirs = set()
            base_parts = name.split("/")[:-1]
            for item in dirlist:
                parts = item['key'].split("/")
                parts = parts[len(base_parts):]
                if len(parts) == 1:
                    # File
                    files.append(parts[0])
                elif len(parts) > 1:
                    # Directory
                    dirs.add(parts[0])
            return list(dirs), files
    
        def url(self, name):
            name = self._normalize_name(self._clean_name(name))
            name = filepath_to_uri(name)
            protocol = u'https://' if self.secure_url else u'http://'
            return urljoin(protocol   self.bucket_domain, name)
    

    安顿是从境况变量可能settings.py中获得的:

    def get_qiniu_config(name, default=None):
        """
        Get configuration variable from environment variable
        or django setting.py
        """
        config = os.environ.get(name, getattr(settings, name, default))
        if config is not None:
            if isinstance(config, six.string_types):
                return config.strip()
            else:
                return config
        else:
            raise ImproperlyConfigured(
                "Can't find config for '%s' either in environment"
                "variable or in setting.py" % name)
    
    
    QINIU_ACCESS_KEY = get_qiniu_config('QINIU_ACCESS_KEY')
    QINIU_SECRET_KEY = get_qiniu_config('QINIU_SECRET_KEY')
    QINIU_BUCKET_NAME = get_qiniu_config('QINIU_BUCKET_NAME')
    QINIU_BUCKET_DOMAIN = get_qiniu_config('QINIU_BUCKET_DOMAIN', '').rstrip('/')
    QINIU_SECURE_URL = get_qiniu_config('QINIU_SECURE_URL', 'False')
    

     重写了_open和_save方法:

        def _open(self, name, mode='rb'):
            return QiniuFile(name, self, mode)
    
        def _save(self, name, content):
            cleaned_name = self._clean_name(name)
            name = self._normalize_name(cleaned_name)
    
            if hasattr(content, 'chunks'):
                content_str = b''.join(chunk for chunk in content.chunks())
            else:
                content_str = content.read()
    
            self._put_file(name, content_str)
            return cleaned_name
    

    使用的put_data方法上传文件,相关代码如下:

    def put_data(
            up_token, key, data, params=None, mime_type='application/octet-stream', check_crc=False, progress_handler=None,
            fname=None):
        """上传二进制流到七牛
    
        Args:
            up_token:         上传凭证
            key:              上传文件名
            data:             上传二进制流
            params:           自定义变量,规格参考 http://developer.qiniu.com/docs/v6/api/overview/up/response/vars.html#xvar
            mime_type:        上传数据的mimeType
            check_crc:        是否校验crc32
            progress_handler: 上传进度
    
        Returns:
            一个dict变量,类似 {"hash": "<Hash string>", "key": "<Key string>"}
            一个ResponseInfo对象
        """
        crc = crc32(data) if check_crc else None
        return _form_put(up_token, key, data, params, mime_type, crc, progress_handler, fname)
    
    def _form_put(up_token, key, data, params, mime_type, crc, progress_handler=None, file_name=None):
        fields = {}
        if params:
            for k, v in params.items():
                fields[k] = str(v)
        if crc:
            fields['crc32'] = crc
        if key is not None:
            fields['key'] = key
    
        fields['token'] = up_token
        url = config.get_default('default_zone').get_up_host_by_token(up_token)   '/'
        # name = key if key else file_name
    
        fname = file_name
        if not fname or not fname.strip():
            fname = 'file_name'
    
        r, info = http._post_file(url, data=fields, files={'file': (fname, data, mime_type)})
        if r is None and info.need_retry():
            if info.connect_failed:
                url = config.get_default('default_zone').get_up_host_backup_by_token(up_token)   '/'
            if hasattr(data, 'read') is False:
                pass
            elif hasattr(data, 'seek') and (not hasattr(data, 'seekable') or data.seekable()):
                data.seek(0)
            else:
                return r, info
            r, info = http._post_file(url, data=fields, files={'file': (fname, data, mime_type)})
    
        return r, info
    
    
    def _post_file(url, data, files):
        return _post(url, data, files, None)
    
    def _post(url, data, files, auth, headers=None):
        if _session is None:
            _init()
        try:
            post_headers = _headers.copy()
            if headers is not None:
                for k, v in headers.items():
                    post_headers.update({k: v})
            r = _session.post(
                url, data=data, files=files, auth=auth, headers=post_headers,
                timeout=config.get_default('connection_timeout'))
        except Exception as e:
            return None, ResponseInfo(None, e)
        return __return_wrapper(r)
    
    
    def _init():
        session = requests.Session()
        adapter = requests.adapters.HTTPAdapter(
            pool_connections=config.get_default('connection_pool'), pool_maxsize=config.get_default('connection_pool'),
            max_retries=config.get_default('connection_retries'))
        session.mount('http://', adapter)
        global _session
        _session = session
    

    最终使用的是requests库上传文件的,统一适配了链接池个数、链接重试次数。

    要团结写贰个仓库储存系统,能够遵守以下步骤: 1.写一个三回九转自django.core.files.storage.Storage 的子...

    1.写二个传承自django.core.files.storage.Storage的子类。

    1.写一个一而再自django.core.files.storage.Storage的子类。

    • 您自定义的存款和储蓄系统一定是django.core.files.storage.Storage的子类

      from django.core.files.storage import Storage

      class MyStorage(Storage):

      ...
      
    from django.core.files.storage import Storage
    
    class MyStorage(Storage):
        ...
    
    from django.core.files.storage import Storage
    
    class MyStorage(Storage):
        ...
    

     

    本文由1010cc时时彩经典版发布于1010cc时时彩经典版,转载请注明出处:【1010cc时时彩经典版】暗许存款和储蓄系统,怎

    关键词: