Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #18515 -- Conditionally regenerated filename in FileField valid…

…ation

When a FileField value has been saved, a new validation should not
regenerate a new filename when checking the length. Refs #9893.
  • Loading branch information...
commit 05d333ba3bb16af024c11966d2072de38fe9f82f 1 parent b6c356b
@claudep claudep authored
View
6 django/db/models/fields/files.py
@@ -242,7 +242,11 @@ def validate(self, value, model_instance):
# (ie. upload_to='path/to/upload/dir'), the length of the generated
# name equals the length of the uploaded name plus a constant. Thus
# we can tell the user how much shorter the name should be (roughly).
- length = len(self.generate_filename(model_instance, value.name))
+ if value and value._committed:
+ filename = value.name
+ else:
+ filename = self.generate_filename(model_instance, value.name)
+ length = len(filename)
if self.max_length and length > self.max_length:
error_values = {'extra': length - self.max_length}
raise ValidationError(self.error_messages['max_length'] % error_values)
View
2  tests/modeltests/files/models.py
@@ -26,5 +26,5 @@ def random_upload_to(self, filename):
normal = models.FileField(storage=temp_storage, upload_to='tests')
custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to)
- random = models.FileField(storage=temp_storage, upload_to=random_upload_to)
+ random = models.FileField(storage=temp_storage, upload_to=random_upload_to, max_length=16)
default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt')
View
23 tests/modeltests/files/tests.py
@@ -5,6 +5,7 @@
import tempfile
from django.core.cache import cache
+from django.core.exceptions import ValidationError
from django.core.files import File
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
@@ -102,11 +103,23 @@ def test_files(self):
obj4.random.save("random_file", ContentFile(b"random content"))
self.assertTrue(obj4.random.name.endswith("/random_file"))
- # Clean up the temporary files and dir.
- obj1.normal.delete()
- obj2.normal.delete()
- obj3.default.delete()
- obj4.random.delete()
+ def test_max_length(self):
+ """
+ Test that FileField validates the length of the generated file name
+ that will be stored in the database. Regression for #9893.
+ """
+ # upload_to = 'unused', so file names are saved as '456/xxxxx'.
+ # max_length = 16, so names longer than 12 characters are rejected.
+ s1 = Storage(random=SimpleUploadedFile(12 * 'x', b"content"))
+ s1.full_clean()
+ with self.assertRaises(ValidationError):
+ Storage(random=SimpleUploadedFile(13 * 'x', b"content")).full_clean()
+
+ # Ticket #18515: validation for an already saved file should not check
+ # against a regenerated file name (and potentially raise a ValidationError
+ # if max_length is exceeded
+ s1.save()
+ s1.full_clean()
class FileTests(unittest.TestCase):
View
12 tests/regressiontests/model_fields/tests.py
@@ -365,15 +365,3 @@ def test_changed(self):
field = d._meta.get_field('myfile')
field.save_form_data(d, 'else.txt')
self.assertEqual(d.myfile, 'else.txt')
-
- def test_max_length(self):
- """
- Test that FileField validates the length of the generated file name
- that will be stored in the database. Regression for #9893.
-
- """
- # upload_to = 'unused', so file names are saved as 'unused/xxxxx'.
- # max_length = 100, so names longer than 93 characters are rejected.
- Document(myfile=93 * 'x').full_clean()
- with self.assertRaises(ValidationError):
- Document(myfile=94 * 'x').full_clean()
Please sign in to comment.
Something went wrong with that request. Please try again.