mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.11.x] Fixed #28242 -- Moved ImageField file extension validation to the form field.
Backport of a0c07d77fc from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Tim Graham
						Tim Graham
					
				
			
			
				
	
			
			
			
						parent
						
							af9a81aa7f
						
					
				
				
					commit
					110bd82038
				
			| @@ -8,7 +8,6 @@ from django.core import checks | ||||
| from django.core.files.base import File | ||||
| from django.core.files.images import ImageFile | ||||
| from django.core.files.storage import default_storage | ||||
| from django.core.validators import validate_image_file_extension | ||||
| from django.db.models import signals | ||||
| from django.db.models.fields import Field | ||||
| from django.utils import six | ||||
| @@ -387,7 +386,6 @@ class ImageFieldFile(ImageFile, FieldFile): | ||||
|  | ||||
|  | ||||
| class ImageField(FileField): | ||||
|     default_validators = [validate_image_file_extension] | ||||
|     attr_class = ImageFieldFile | ||||
|     descriptor_class = ImageFileDescriptor | ||||
|     description = _("Image") | ||||
|   | ||||
| @@ -610,6 +610,7 @@ class FileField(Field): | ||||
|  | ||||
|  | ||||
| class ImageField(FileField): | ||||
|     default_validators = [validators.validate_image_file_extension] | ||||
|     default_error_messages = { | ||||
|         'invalid_image': _( | ||||
|             "Upload a valid image. The file you uploaded was either not an " | ||||
|   | ||||
| @@ -58,3 +58,7 @@ Bugfixes | ||||
|  | ||||
| * Fixed a regression where ``file_move_safe()`` crashed when moving files to a | ||||
|   CIFS mount (:ticket:`28170`). | ||||
|  | ||||
| * Moved the ``ImageField`` file extension validation added in Django 1.11 from | ||||
|   the model field to the form field to reallow the use case of storing images | ||||
|   without an extension (:ticket:`28242`). | ||||
|   | ||||
| @@ -327,6 +327,7 @@ Models | ||||
|  | ||||
| * :class:`~django.db.models.ImageField` now has a default | ||||
|   :data:`~django.core.validators.validate_image_file_extension` validator. | ||||
|   (This validator moved to the form field in :doc:`Django 1.11.2 <1.11.2>`.) | ||||
|  | ||||
| * Added support for time truncation to | ||||
|   :class:`~django.db.models.functions.datetime.Trunc` functions. | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import os | ||||
| import unittest | ||||
|  | ||||
| from django.core.files.uploadedfile import SimpleUploadedFile | ||||
| from django.forms import ImageField | ||||
| from django.forms import ImageField, ValidationError | ||||
| from django.test import SimpleTestCase | ||||
| from django.utils._os import upath | ||||
|  | ||||
| @@ -58,3 +58,12 @@ class ImageFieldTest(SimpleTestCase): | ||||
|             self.assertIsNone(uploaded_file.content_type) | ||||
|         finally: | ||||
|             Image.register_mime(BmpImageFile.format, 'image/bmp') | ||||
|  | ||||
|     def test_file_extension_validation(self): | ||||
|         f = ImageField() | ||||
|         img_path = get_img_path('filepath_test_files/1x1.png') | ||||
|         with open(img_path, 'rb') as img_file: | ||||
|             img_data = img_file.read() | ||||
|         img_file = SimpleUploadedFile('1x1.txt', img_data) | ||||
|         with self.assertRaisesMessage(ValidationError, "File extension 'txt' is not allowed."): | ||||
|             f.clean(img_file) | ||||
|   | ||||
| @@ -4,7 +4,7 @@ import os | ||||
| import shutil | ||||
| from unittest import skipIf | ||||
|  | ||||
| from django.core.exceptions import ImproperlyConfigured, ValidationError | ||||
| from django.core.exceptions import ImproperlyConfigured | ||||
| from django.core.files import File | ||||
| from django.core.files.images import ImageFile | ||||
| from django.test import TestCase | ||||
| @@ -133,12 +133,6 @@ class ImageFieldTests(ImageFieldTestMixin, TestCase): | ||||
|         self.assertEqual(hash(p1_db.mugshot), hash(p1.mugshot)) | ||||
|         self.assertIs(p1_db.mugshot != p1.mugshot, False) | ||||
|  | ||||
|     def test_validation(self): | ||||
|         p = self.PersonModel(name="Joan") | ||||
|         p.mugshot.save("shot.txt", self.file1) | ||||
|         with self.assertRaisesMessage(ValidationError, "File extension 'txt' is not allowed."): | ||||
|             p.full_clean() | ||||
|  | ||||
|     def test_instantiate_missing(self): | ||||
|         """ | ||||
|         If the underlying file is unavailable, still create instantiate the | ||||
|   | ||||
| @@ -214,6 +214,17 @@ try: | ||||
|  | ||||
|         def __str__(self): | ||||
|             return self.description | ||||
|  | ||||
|     class NoExtensionImageFile(models.Model): | ||||
|         def upload_to(self, filename): | ||||
|             return 'tests/no_extension' | ||||
|  | ||||
|         description = models.CharField(max_length=20) | ||||
|         image = models.ImageField(storage=temp_storage, upload_to=upload_to) | ||||
|  | ||||
|         def __str__(self): | ||||
|             return self.description | ||||
|  | ||||
| except ImportError: | ||||
|     test_images = False | ||||
|  | ||||
|   | ||||
| @@ -36,7 +36,7 @@ from .models import ( | ||||
| ) | ||||
|  | ||||
| if test_images: | ||||
|     from .models import ImageFile, OptionalImageFile | ||||
|     from .models import ImageFile, OptionalImageFile, NoExtensionImageFile | ||||
|  | ||||
|     class ImageFileForm(forms.ModelForm): | ||||
|         class Meta: | ||||
| @@ -48,6 +48,11 @@ if test_images: | ||||
|             model = OptionalImageFile | ||||
|             fields = '__all__' | ||||
|  | ||||
|     class NoExtensionImageFileForm(forms.ModelForm): | ||||
|         class Meta: | ||||
|             model = NoExtensionImageFile | ||||
|             fields = '__all__' | ||||
|  | ||||
|  | ||||
| class ProductForm(forms.ModelForm): | ||||
|     class Meta: | ||||
| @@ -2469,6 +2474,19 @@ class FileAndImageFieldTests(TestCase): | ||||
|         self.assertEqual(instance.image.name, 'foo/test4.png') | ||||
|         instance.delete() | ||||
|  | ||||
|         # Editing an instance that has an image without an extension shouldn't | ||||
|         # fail validation. First create: | ||||
|         f = NoExtensionImageFileForm( | ||||
|             data={'description': 'An image'}, | ||||
|             files={'image': SimpleUploadedFile('test.png', image_data)}, | ||||
|         ) | ||||
|         self.assertTrue(f.is_valid()) | ||||
|         instance = f.save() | ||||
|         self.assertEqual(instance.image.name, 'tests/no_extension') | ||||
|         # Then edit: | ||||
|         f = NoExtensionImageFileForm(data={'description': 'Edited image'}, instance=instance) | ||||
|         self.assertTrue(f.is_valid()) | ||||
|  | ||||
|  | ||||
| class ModelOtherFieldTests(SimpleTestCase): | ||||
|     def test_big_integer_field(self): | ||||
|   | ||||
		Reference in New Issue
	
	Block a user