mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #23103 -- Annotated ImageField file with image and content_type attributes.
Thanks Jeremy Dunck for the suggestion and Nick Sanford for review.
This commit is contained in:
		
				
					committed by
					
						 Tim Graham
						Tim Graham
					
				
			
			
				
	
			
			
			
						parent
						
							8c2b405ba8
						
					
				
				
					commit
					8b7347220f
				
			| @@ -659,8 +659,13 @@ class ImageField(FileField): | |||||||
|         try: |         try: | ||||||
|             # load() could spot a truncated JPEG, but it loads the entire |             # load() could spot a truncated JPEG, but it loads the entire | ||||||
|             # image in memory, which is a DoS vector. See #3848 and #18520. |             # image in memory, which is a DoS vector. See #3848 and #18520. | ||||||
|  |             image = Image.open(file) | ||||||
|             # verify() must be called immediately after the constructor. |             # verify() must be called immediately after the constructor. | ||||||
|             Image.open(file).verify() |             image.verify() | ||||||
|  |  | ||||||
|  |             # Annotating so subclasses can reuse it for their own validation | ||||||
|  |             f.image = image | ||||||
|  |             f.content_type = Image.MIME[image.format] | ||||||
|         except Exception: |         except Exception: | ||||||
|             # Pillow doesn't recognize it as an image. |             # Pillow doesn't recognize it as an image. | ||||||
|             six.reraise(ValidationError, ValidationError( |             six.reraise(ValidationError, ValidationError( | ||||||
|   | |||||||
| @@ -649,7 +649,16 @@ For each field, we describe the default widget used if you don't specify | |||||||
|     When you use an ``ImageField`` on a form, you must also remember to |     When you use an ``ImageField`` on a form, you must also remember to | ||||||
|     :ref:`bind the file data to the form <binding-uploaded-files>`. |     :ref:`bind the file data to the form <binding-uploaded-files>`. | ||||||
|  |  | ||||||
|  |     .. versionchanged:: 1.8 | ||||||
|  |  | ||||||
|  |         After the field has been cleaned and validated, the ``UploadedFile`` | ||||||
|  |         object will have an additional ``image`` attribute containing the Pillow | ||||||
|  |         `Image`_ instance used to check if the file was a valid image. | ||||||
|  |         ``UploadedFile.content_type`` is also updated with the image's content | ||||||
|  |         type as determined by Pillow. | ||||||
|  |  | ||||||
| .. _Pillow: http://pillow.readthedocs.org/en/latest/ | .. _Pillow: http://pillow.readthedocs.org/en/latest/ | ||||||
|  | .. _Image: https://pillow.readthedocs.org/en/latest/reference/Image.html | ||||||
|  |  | ||||||
| ``IntegerField`` | ``IntegerField`` | ||||||
| ~~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~~ | ||||||
|   | |||||||
| @@ -160,6 +160,12 @@ Forms | |||||||
|   :attr:`~django.forms.extras.widgets.SelectDateWidget.empty_label` argument, which will |   :attr:`~django.forms.extras.widgets.SelectDateWidget.empty_label` argument, which will | ||||||
|   override the top list choice label when :class:`~django.forms.DateField` is not required. |   override the top list choice label when :class:`~django.forms.DateField` is not required. | ||||||
|  |  | ||||||
|  | * After an :class:`~django.forms.ImageField` has been cleaned and validated, the | ||||||
|  |   ``UploadedFile`` object will have an additional ``image`` attribute containing | ||||||
|  |   the Pillow ``Image`` instance used to check if the file was a valid image. It | ||||||
|  |   will also update ``UploadedFile.content_type`` with the image's content type | ||||||
|  |   as determined by Pillow. | ||||||
|  |  | ||||||
| Internationalization | Internationalization | ||||||
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^ | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								tests/forms_tests/tests/filepath_test_files/1x1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tests/forms_tests/tests/filepath_test_files/1x1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 150 B | 
| @@ -31,12 +31,18 @@ import pickle | |||||||
| import re | import re | ||||||
| import os | import os | ||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
|  | from unittest import skipIf | ||||||
|  |  | ||||||
|  | try: | ||||||
|  |     from PIL import Image | ||||||
|  | except ImportError: | ||||||
|  |     Image = None | ||||||
|  |  | ||||||
| from django.core.files.uploadedfile import SimpleUploadedFile | from django.core.files.uploadedfile import SimpleUploadedFile | ||||||
| from django.forms import ( | from django.forms import ( | ||||||
|     BooleanField, CharField, ChoiceField, ComboField, DateField, DateTimeField, |     BooleanField, CharField, ChoiceField, ComboField, DateField, DateTimeField, | ||||||
|     DecimalField, EmailField, Field, FileField, FilePathField, FloatField, |     DecimalField, EmailField, Field, FileField, FilePathField, FloatField, | ||||||
|     Form, forms, HiddenInput, IntegerField, MultipleChoiceField, |     Form, forms, HiddenInput, ImageField, IntegerField, MultipleChoiceField, | ||||||
|     NullBooleanField, NumberInput, PasswordInput, RadioSelect, RegexField, |     NullBooleanField, NumberInput, PasswordInput, RadioSelect, RegexField, | ||||||
|     SplitDateTimeField, TextInput, Textarea, TimeField, TypedChoiceField, |     SplitDateTimeField, TextInput, Textarea, TimeField, TypedChoiceField, | ||||||
|     TypedMultipleChoiceField, URLField, ValidationError, Widget, |     TypedMultipleChoiceField, URLField, ValidationError, Widget, | ||||||
| @@ -741,6 +747,24 @@ class FieldsTests(SimpleTestCase): | |||||||
|         # with here) |         # with here) | ||||||
|         self.assertTrue(f._has_changed('resume.txt', {'filename': 'resume.txt', 'content': 'My resume'})) |         self.assertTrue(f._has_changed('resume.txt', {'filename': 'resume.txt', 'content': 'My resume'})) | ||||||
|  |  | ||||||
|  |     # ImageField ################################################################## | ||||||
|  |  | ||||||
|  |     @skipIf(Image is None, "Pillow is required to test ImageField") | ||||||
|  |     def test_imagefield_annotate_with_image_after_clean(self): | ||||||
|  |         f = ImageField() | ||||||
|  |  | ||||||
|  |         img_path = os.path.dirname(upath(__file__)) + '/filepath_test_files/1x1.png' | ||||||
|  |         with open(img_path, 'rb') as img_file: | ||||||
|  |             img_data = img_file.read() | ||||||
|  |  | ||||||
|  |         img_file = SimpleUploadedFile('1x1.png', img_data) | ||||||
|  |         img_file.content_type = 'text/plain' | ||||||
|  |  | ||||||
|  |         uploaded_file = f.clean(img_file) | ||||||
|  |  | ||||||
|  |         self.assertEqual('PNG', uploaded_file.image.format) | ||||||
|  |         self.assertEqual('image/png', uploaded_file.content_type) | ||||||
|  |  | ||||||
|     # URLField ################################################################## |     # URLField ################################################################## | ||||||
|  |  | ||||||
|     def test_urlfield_1(self): |     def test_urlfield_1(self): | ||||||
| @@ -1262,6 +1286,7 @@ class FieldsTests(SimpleTestCase): | |||||||
|         f.choices.sort() |         f.choices.sort() | ||||||
|         expected = [ |         expected = [ | ||||||
|             ('/tests/forms_tests/tests/filepath_test_files/.dot-file', '.dot-file'), |             ('/tests/forms_tests/tests/filepath_test_files/.dot-file', '.dot-file'), | ||||||
|  |             ('/tests/forms_tests/tests/filepath_test_files/1x1.png', '1x1.png'), | ||||||
|             ('/tests/forms_tests/tests/filepath_test_files/directory', 'directory'), |             ('/tests/forms_tests/tests/filepath_test_files/directory', 'directory'), | ||||||
|             ('/tests/forms_tests/tests/filepath_test_files/fake-image.jpg', 'fake-image.jpg'), |             ('/tests/forms_tests/tests/filepath_test_files/fake-image.jpg', 'fake-image.jpg'), | ||||||
|             ('/tests/forms_tests/tests/filepath_test_files/real-text-file.txt', 'real-text-file.txt'), |             ('/tests/forms_tests/tests/filepath_test_files/real-text-file.txt', 'real-text-file.txt'), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user