diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
index e0c0959..b0dce38 100644
a
|
b
|
class FileField(Field):
|
242 | 242 | # (ie. upload_to='path/to/upload/dir'), the length of the generated |
243 | 243 | # name equals the length of the uploaded name plus a constant. Thus |
244 | 244 | # we can tell the user how much shorter the name should be (roughly). |
245 | | length = len(self.generate_filename(model_instance, value.name)) |
| 245 | if value and value._committed: |
| 246 | filename = value.name |
| 247 | else: |
| 248 | filename = self.generate_filename(model_instance, value.name) |
| 249 | length = len(filename) |
246 | 250 | if self.max_length and length > self.max_length: |
247 | 251 | error_values = {'extra': length - self.max_length} |
248 | 252 | raise ValidationError(self.error_messages['max_length'] % error_values) |
diff --git a/tests/modeltests/files/models.py b/tests/modeltests/files/models.py
index 4134472..cefc7c7 100644
a
|
b
|
class Storage(models.Model):
|
26 | 26 | |
27 | 27 | normal = models.FileField(storage=temp_storage, upload_to='tests') |
28 | 28 | custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) |
29 | | random = models.FileField(storage=temp_storage, upload_to=random_upload_to) |
| 29 | random = models.FileField(storage=temp_storage, upload_to=random_upload_to, max_length=16) |
30 | 30 | default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt') |
diff --git a/tests/modeltests/files/tests.py b/tests/modeltests/files/tests.py
index 3e256f7..565d4c8 100644
a
|
b
|
import shutil
|
5 | 5 | import tempfile |
6 | 6 | |
7 | 7 | from django.core.cache import cache |
| 8 | from django.core.exceptions import ValidationError |
8 | 9 | from django.core.files import File |
9 | 10 | from django.core.files.base import ContentFile |
10 | 11 | from django.core.files.uploadedfile import SimpleUploadedFile |
… |
… |
class FileStorageTests(TestCase):
|
102 | 103 | obj4.random.save("random_file", ContentFile(b"random content")) |
103 | 104 | self.assertTrue(obj4.random.name.endswith("/random_file")) |
104 | 105 | |
105 | | # Clean up the temporary files and dir. |
106 | | obj1.normal.delete() |
107 | | obj2.normal.delete() |
108 | | obj3.default.delete() |
109 | | obj4.random.delete() |
| 106 | def test_max_length(self): |
| 107 | """ |
| 108 | Test that FileField validates the length of the generated file name |
| 109 | that will be stored in the database. Regression for #9893. |
| 110 | """ |
| 111 | # upload_to = 'unused', so file names are saved as '456/xxxxx'. |
| 112 | # max_length = 16, so names longer than 12 characters are rejected. |
| 113 | s1 = Storage(random=SimpleUploadedFile(12 * 'x', b"content")) |
| 114 | s1.full_clean() |
| 115 | with self.assertRaises(ValidationError): |
| 116 | Storage(random=SimpleUploadedFile(13 * 'x', b"content")).full_clean() |
| 117 | |
| 118 | # Ticket #18515: validation for an already saved file should not check |
| 119 | # against a regenerated file name (and potentially raise a ValidationError |
| 120 | # if max_length is exceeded |
| 121 | s1.save() |
| 122 | s1.full_clean() |
110 | 123 | |
111 | 124 | |
112 | 125 | class FileTests(unittest.TestCase): |
diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py
index 5d3d42e..a89ffca 100644
a
|
b
|
class FileFieldTests(unittest.TestCase):
|
365 | 365 | field = d._meta.get_field('myfile') |
366 | 366 | field.save_form_data(d, 'else.txt') |
367 | 367 | self.assertEqual(d.myfile, 'else.txt') |
368 | | |
369 | | def test_max_length(self): |
370 | | """ |
371 | | Test that FileField validates the length of the generated file name |
372 | | that will be stored in the database. Regression for #9893. |
373 | | |
374 | | """ |
375 | | # upload_to = 'unused', so file names are saved as 'unused/xxxxx'. |
376 | | # max_length = 100, so names longer than 93 characters are rejected. |
377 | | Document(myfile=93 * 'x').full_clean() |
378 | | with self.assertRaises(ValidationError): |
379 | | Document(myfile=94 * 'x').full_clean() |