mirror of
https://github.com/django/django.git
synced 2025-10-24 06:06:09 +00:00
Fixed #9893 -- Allowed using a field's max_length in the Storage.
This commit is contained in:
committed by
Tim Graham
parent
b5c1a85b50
commit
a7c256cb54
@@ -8,6 +8,7 @@ import sys
|
||||
import tempfile
|
||||
import time
|
||||
import unittest
|
||||
import warnings
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
try:
|
||||
@@ -16,7 +17,7 @@ except ImportError:
|
||||
import dummy_threading as threading
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
from django.core.exceptions import SuspiciousOperation, SuspiciousFileOperation
|
||||
from django.core.files.base import File, ContentFile
|
||||
from django.core.files.storage import FileSystemStorage, get_storage_class
|
||||
from django.core.files.uploadedfile import (InMemoryUploadedFile, SimpleUploadedFile,
|
||||
@@ -407,7 +408,7 @@ class FileStorageTests(unittest.TestCase):
|
||||
|
||||
|
||||
class CustomStorage(FileSystemStorage):
|
||||
def get_available_name(self, name):
|
||||
def get_available_name(self, name, max_length=None):
|
||||
"""
|
||||
Append numbers to duplicate files rather than underscores, like Trac.
|
||||
"""
|
||||
@@ -433,7 +434,7 @@ class CustomStorageTests(FileStorageTests):
|
||||
self.storage.delete(second)
|
||||
|
||||
|
||||
class FileFieldStorageTests(unittest.TestCase):
|
||||
class FileFieldStorageTests(SimpleTestCase):
|
||||
def tearDown(self):
|
||||
shutil.rmtree(temp_storage_location)
|
||||
|
||||
@@ -503,6 +504,69 @@ class FileFieldStorageTests(unittest.TestCase):
|
||||
for o in objs:
|
||||
o.delete()
|
||||
|
||||
def test_file_truncation(self):
|
||||
# Given the max_length is limited, when multiple files get uploaded
|
||||
# under the same name, then the filename get truncated in order to fit
|
||||
# in _(7 random chars). When most of the max_length is taken by
|
||||
# dirname + extension and there are not enough characters in the
|
||||
# filename to truncate, an exception should be raised.
|
||||
objs = [Storage() for i in range(2)]
|
||||
filename = 'filename.ext'
|
||||
|
||||
for o in objs:
|
||||
o.limited_length.save(filename, ContentFile('Same Content'))
|
||||
try:
|
||||
# Testing truncation.
|
||||
names = [o.limited_length.name for o in objs]
|
||||
self.assertEqual(names[0], 'tests/%s' % filename)
|
||||
six.assertRegex(self, names[1], 'tests/fi_%s.ext' % FILE_SUFFIX_REGEX)
|
||||
|
||||
# Testing exception is raised when filename is too short to truncate.
|
||||
filename = 'short.longext'
|
||||
objs[0].limited_length.save(filename, ContentFile('Same Content'))
|
||||
self.assertRaisesMessage(
|
||||
SuspiciousFileOperation, 'Storage can not find an available filename',
|
||||
objs[1].limited_length.save, *(filename, ContentFile('Same Content'))
|
||||
)
|
||||
finally:
|
||||
for o in objs:
|
||||
o.delete()
|
||||
|
||||
def test_extended_length_storage(self):
|
||||
# Testing FileField with max_length > 255. Most systems have filename
|
||||
# length limitation of 255. Path takes extra chars.
|
||||
filename = 251 * 'a' # 4 chars for extension.
|
||||
obj = Storage()
|
||||
obj.extended_length.save('%s.txt' % filename, ContentFile('Same Content'))
|
||||
self.assertEqual(obj.extended_length.name, 'tests/%s.txt' % filename)
|
||||
self.assertEqual(obj.extended_length.read(), b'Same Content')
|
||||
obj.extended_length.close()
|
||||
|
||||
def test_old_style_storage(self):
|
||||
# Testing backward-compatibility with old-style storage backends that
|
||||
# don't take ``max_length`` parameter in ``get_available_name()``
|
||||
# and save(). A deprecation warning should be raised.
|
||||
obj = Storage()
|
||||
with warnings.catch_warnings(record=True) as warns:
|
||||
warnings.simplefilter('always')
|
||||
obj.old_style.save('deprecated_storage_test.txt', ContentFile('Same Content'))
|
||||
self.assertEqual(len(warns), 2)
|
||||
self.assertEqual(
|
||||
str(warns[0].message),
|
||||
'Backwards compatibility for storage backends without support for '
|
||||
'the `max_length` argument in Storage.save() will be removed in '
|
||||
'Django 2.0.'
|
||||
)
|
||||
self.assertEqual(
|
||||
str(warns[1].message),
|
||||
'Backwards compatibility for storage backends without support for '
|
||||
'the `max_length` argument in Storage.get_available_name() will '
|
||||
'be removed in Django 2.0.'
|
||||
)
|
||||
self.assertEqual(obj.old_style.name, 'tests/deprecated_storage_test.txt')
|
||||
self.assertEqual(obj.old_style.read(), b'Same Content')
|
||||
obj.old_style.close()
|
||||
|
||||
def test_filefield_default(self):
|
||||
# Default values allow an object to access a single file.
|
||||
temp_storage.save('tests/default.txt', ContentFile('default content'))
|
||||
|
||||
Reference in New Issue
Block a user