9
9
from django.utils.crypto import get_random_string
10
10
from django.utils.encoding import force_text, filepath_to_uri
11
11
from django.utils.functional import LazyObject
12
from django.utils.module_loading import import_by_path
12
from django.utils.module_loading import import_string
13
13
from django.utils.six.moves.urllib.parse import urljoin
14
14
from django.utils.text import get_valid_filename
15
15
from django.utils._os import safe_join, abspathu
16
from django.utils.deconstruct import deconstructible
18
19
__all__ = ('Storage', 'FileSystemStorage', 'DefaultStorage', 'default_storage')
20
22
class Storage(object):
22
24
A base storage class, providing some default behaviors that all other
92
94
Deletes the specified file from the storage system.
94
raise NotImplementedError()
96
raise NotImplementedError('subclasses of Storage must provide a delete() method')
96
98
def exists(self, name):
98
Returns True if a file referened by the given name already exists in the
100
Returns True if a file referenced by the given name already exists in the
99
101
storage system, or False if the name is available for a new file.
101
raise NotImplementedError()
103
raise NotImplementedError('subclasses of Storage must provide an exists() method')
103
105
def listdir(self, path):
105
107
Lists the contents of the specified path, returning a 2-tuple of lists;
106
108
the first item being directories, the second item being files.
108
raise NotImplementedError()
110
raise NotImplementedError('subclasses of Storage must provide a listdir() method')
110
112
def size(self, name):
112
114
Returns the total size, in bytes, of the file specified by name.
114
raise NotImplementedError()
116
raise NotImplementedError('subclasses of Storage must provide a size() method')
116
118
def url(self, name):
118
120
Returns an absolute URL where the file's contents can be accessed
119
121
directly by a Web browser.
121
raise NotImplementedError()
123
raise NotImplementedError('subclasses of Storage must provide a url() method')
123
125
def accessed_time(self, name):
125
127
Returns the last accessed time (as datetime object) of the file
126
128
specified by name.
128
raise NotImplementedError()
130
raise NotImplementedError('subclasses of Storage must provide an accessed_time() method')
130
132
def created_time(self, name):
132
134
Returns the creation time (as datetime object) of the file
133
135
specified by name.
135
raise NotImplementedError()
137
raise NotImplementedError('subclasses of Storage must provide a created_time() method')
137
139
def modified_time(self, name):
139
141
Returns the last modified time (as datetime object) of the file
140
142
specified by name.
142
raise NotImplementedError()
144
raise NotImplementedError('subclasses of Storage must provide a modified_time() method')
144
148
class FileSystemStorage(Storage):
146
150
Standard filesystem storage
149
def __init__(self, location=None, base_url=None):
153
def __init__(self, location=None, base_url=None, file_permissions_mode=None,
154
directory_permissions_mode=None):
150
155
if location is None:
151
156
location = settings.MEDIA_ROOT
152
157
self.base_location = location
154
159
if base_url is None:
155
160
base_url = settings.MEDIA_URL
156
161
self.base_url = base_url
162
self.file_permissions_mode = (
163
file_permissions_mode if file_permissions_mode is not None
164
else settings.FILE_UPLOAD_PERMISSIONS
166
self.directory_permissions_mode = (
167
directory_permissions_mode if directory_permissions_mode is not None
168
else settings.FILE_UPLOAD_DIRECTORY_PERMISSIONS
158
171
def _open(self, name, mode='rb'):
159
172
return File(open(self.path(name), mode))
168
181
directory = os.path.dirname(full_path)
169
182
if not os.path.exists(directory):
171
os.makedirs(directory)
184
if self.directory_permissions_mode is not None:
185
# os.makedirs applies the global umask, so we reset it,
186
# for consistency with file_permissions_mode behavior.
187
old_umask = os.umask(0)
189
os.makedirs(directory, self.directory_permissions_mode)
193
os.makedirs(directory)
172
194
except OSError as e:
173
195
if e.errno != errno.EEXIST:
221
242
# OK, the file save worked. Break out of the loop.
224
if settings.FILE_UPLOAD_PERMISSIONS is not None:
225
os.chmod(full_path, settings.FILE_UPLOAD_PERMISSIONS)
245
if self.file_permissions_mode is not None:
246
os.chmod(full_path, self.file_permissions_mode)
277
298
def modified_time(self, name):
278
299
return datetime.fromtimestamp(os.path.getmtime(self.path(name)))
280
302
def get_storage_class(import_path=None):
281
return import_by_path(import_path or settings.DEFAULT_FILE_STORAGE)
303
return import_string(import_path or settings.DEFAULT_FILE_STORAGE)
283
306
class DefaultStorage(LazyObject):
284
307
def _setup(self):