Fixed #30736 -- Added Storage.get_alternative_name() to allow customization.
This commit is contained in:
parent
400ec5125e
commit
0545781764
|
@ -60,6 +60,14 @@ class Storage:
|
||||||
"""
|
"""
|
||||||
return get_valid_filename(name)
|
return get_valid_filename(name)
|
||||||
|
|
||||||
|
def get_alternative_name(self, file_root, file_ext):
|
||||||
|
"""
|
||||||
|
Return an alternative filename, by adding an underscore and a random 7
|
||||||
|
character alphanumeric string (before the file extension, if one
|
||||||
|
exists) to the filename.
|
||||||
|
"""
|
||||||
|
return '%s_%s%s' % (file_root, get_random_string(7), file_ext)
|
||||||
|
|
||||||
def get_available_name(self, name, max_length=None):
|
def get_available_name(self, name, max_length=None):
|
||||||
"""
|
"""
|
||||||
Return a filename that's free on the target storage system and
|
Return a filename that's free on the target storage system and
|
||||||
|
@ -67,14 +75,13 @@ class Storage:
|
||||||
"""
|
"""
|
||||||
dir_name, file_name = os.path.split(name)
|
dir_name, file_name = os.path.split(name)
|
||||||
file_root, file_ext = os.path.splitext(file_name)
|
file_root, file_ext = os.path.splitext(file_name)
|
||||||
# If the filename already exists, add an underscore and a random 7
|
# If the filename already exists, generate an alternative filename
|
||||||
# character alphanumeric string (before the file extension, if one
|
# until it doesn't exist.
|
||||||
# exists) to the filename until the generated filename doesn't exist.
|
|
||||||
# Truncate original name if required, so the new filename does not
|
# Truncate original name if required, so the new filename does not
|
||||||
# exceed the max_length.
|
# exceed the max_length.
|
||||||
while self.exists(name) or (max_length and len(name) > max_length):
|
while self.exists(name) or (max_length and len(name) > max_length):
|
||||||
# file_ext includes the dot.
|
# file_ext includes the dot.
|
||||||
name = os.path.join(dir_name, "%s_%s%s" % (file_root, get_random_string(7), file_ext))
|
name = os.path.join(dir_name, self.get_alternative_name(file_root, file_ext))
|
||||||
if max_length is None:
|
if max_length is None:
|
||||||
continue
|
continue
|
||||||
# Truncate file_root if max_length exceeded.
|
# Truncate file_root if max_length exceeded.
|
||||||
|
@ -88,7 +95,7 @@ class Storage:
|
||||||
'Please make sure that the corresponding file field '
|
'Please make sure that the corresponding file field '
|
||||||
'allows sufficient "max_length".' % name
|
'allows sufficient "max_length".' % name
|
||||||
)
|
)
|
||||||
name = os.path.join(dir_name, "%s_%s%s" % (file_root, get_random_string(7), file_ext))
|
name = os.path.join(dir_name, self.get_alternative_name(file_root, file_ext))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def generate_filename(self, filename):
|
def generate_filename(self, filename):
|
||||||
|
|
|
@ -97,6 +97,12 @@ non-standard characters are converted to safe filenames.
|
||||||
The code provided on ``Storage`` retains only alpha-numeric characters, periods
|
The code provided on ``Storage`` retains only alpha-numeric characters, periods
|
||||||
and underscores from the original filename, removing everything else.
|
and underscores from the original filename, removing everything else.
|
||||||
|
|
||||||
|
.. method:: get_alternative_name(file_root, file_ext)
|
||||||
|
|
||||||
|
Returns an alternative filename based on the ``file_root`` and ``file_ext``
|
||||||
|
parameters. By default, an underscore plus a random 7 character alphanumeric
|
||||||
|
string is appended to the filename before the extension.
|
||||||
|
|
||||||
.. method:: get_available_name(name, max_length=None)
|
.. method:: get_available_name(name, max_length=None)
|
||||||
|
|
||||||
Returns a filename that is available in the storage mechanism, possibly taking
|
Returns a filename that is available in the storage mechanism, possibly taking
|
||||||
|
@ -108,5 +114,5 @@ The length of the filename will not exceed ``max_length``, if provided. If a
|
||||||
free unique filename cannot be found, a :exc:`SuspiciousFileOperation
|
free unique filename cannot be found, a :exc:`SuspiciousFileOperation
|
||||||
<django.core.exceptions.SuspiciousOperation>` exception is raised.
|
<django.core.exceptions.SuspiciousOperation>` exception is raised.
|
||||||
|
|
||||||
If a file with ``name`` already exists, an underscore plus a random 7 character
|
If a file with ``name`` already exists, ``get_alternative_name()`` is called to
|
||||||
alphanumeric string is appended to the filename before the extension.
|
obtain an alternative name.
|
||||||
|
|
|
@ -105,6 +105,12 @@ The ``Storage`` class
|
||||||
If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``,
|
If :setting:`USE_TZ` is ``True``, returns an aware ``datetime``,
|
||||||
otherwise returns a naive ``datetime`` in the local timezone.
|
otherwise returns a naive ``datetime`` in the local timezone.
|
||||||
|
|
||||||
|
.. method:: get_alternative_name(file_root, file_ext)
|
||||||
|
|
||||||
|
Returns an alternative filename based on the ``file_root`` and
|
||||||
|
``file_ext`` parameters, an underscore plus a random 7 character
|
||||||
|
alphanumeric string is appended to the filename before the extension.
|
||||||
|
|
||||||
.. method:: get_available_name(name, max_length=None)
|
.. method:: get_available_name(name, max_length=None)
|
||||||
|
|
||||||
Returns a filename based on the ``name`` parameter that's free and
|
Returns a filename based on the ``name`` parameter that's free and
|
||||||
|
@ -116,9 +122,8 @@ The ``Storage`` class
|
||||||
:exc:`SuspiciousFileOperation
|
:exc:`SuspiciousFileOperation
|
||||||
<django.core.exceptions.SuspiciousOperation>` exception will be raised.
|
<django.core.exceptions.SuspiciousOperation>` exception will be raised.
|
||||||
|
|
||||||
If a file with ``name`` already exists, an underscore plus a random
|
If a file with ``name`` already exists, :meth:`get_alternative_name` is
|
||||||
7 character alphanumeric string is appended to the filename before
|
called to obtain an alternative name.
|
||||||
the extension.
|
|
||||||
|
|
||||||
.. method:: get_created_time(name)
|
.. method:: get_created_time(name)
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,9 @@ Email
|
||||||
File Storage
|
File Storage
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
* ...
|
* The new :meth:`.Storage.get_alternative_name` method allows customizing the
|
||||||
|
algorithm for generating filenames if a file with the uploaded name already
|
||||||
|
exists.
|
||||||
|
|
||||||
File Uploads
|
File Uploads
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
Loading…
Reference in New Issue