Skip to content
Snippets Groups Projects
files.py 2.94 KiB
Newer Older
  • Learn to ignore specific revisions
  • import os
    
    from django.core.files.base import File
    from django.core.files.storage import default_storage
    from django.core.serializers.json import DjangoJSONEncoder
    
    
    class StreamFieldDataEncoder(DjangoJSONEncoder):
        def default(self, o):
            if isinstance(o, StreamFieldFile):
                return {
    
    Todd Dembrey's avatar
    Todd Dembrey committed
                    'name': o.name,
    
                    'filename': o.filename,
    
                }
            return super().default(o)
    
    
    class StreamFieldFile(File):
    
        def __init__(self, *args, filename=None, storage=default_storage, **kwargs):
    
            super().__init__(*args, **kwargs)
            self.storage = storage
    
            self.filename = filename or os.path.basename(self.name)
    
            self._committed = False
    
        def __str__(self):
            return self.filename
    
    
        def __eq__(self, other):
    
            if isinstance(other, File):
                return self.filename == other.filename and self.size == other.size
            # Rely on the other object to know how to check equality
            # Could cause infinite loop if the other object is unsure how to compare
            return other.__eq__(self)
    
    
        def _get_file(self):
            if getattr(self, '_file', None) is None:
                self._file = self.storage.open(self.name, 'rb')
            return self._file
    
        def _set_file(self, file):
            self._file = file
    
        def _del_file(self):
            del self._file
    
        file = property(_get_file, _set_file, _del_file)
    
    
        def read(self, chunk_size=None):
    
            if chunk_size:
                return super().read(chunk_size)
            else:
                return super().read()
    
        @property
        def path(self):
            return self.storage.path(self.name)
    
        @property
        def url(self):
            return self.storage.url(self.name)
    
        @property
        def size(self):
            if not self._committed:
                return self.file.size
            return self.storage.size(self.name)
    
        def open(self, mode='rb'):
            if getattr(self, '_file', None) is None:
                self.file = self.storage.open(self.name, mode)
            else:
                self.file.open(mode)
            return self
    
        def save(self, folder):
    
    Todd Dembrey's avatar
    Todd Dembrey committed
            name = self.name
            if not name.startswith(folder):
                name = os.path.join(folder, name)
            name = self.storage.generate_filename(name)
    
            if not self._committed:
                self.name = self.storage.save(name, self.file)
    
            self._committed = True
    
        def delete(self, save=True):
            if not self:
                return
            # Only close the file if it's already open, which we know by the
            # presence of self._file
            if hasattr(self, '_file'):
                self.close()
                del self.file
    
            self.storage.delete(self.name)
    
            self.name = None
            self._committed = False
    
        @property
        def closed(self):
            file = getattr(self, '_file', None)
            return file is None or file.closed
    
        def close(self):
            file = getattr(self, '_file', None)
            if file is not None:
                file.close()