diff --git a/django/forms/fields.py b/django/forms/fields.py index ebc25610ee..53520530b6 100644 --- a/django/forms/fields.py +++ b/django/forms/fields.py @@ -692,7 +692,9 @@ class ImageField(FileField): # Annotating so subclasses can reuse it for their own validation f.image = image - f.content_type = Image.MIME[image.format] + # Pillow doesn't detect the MIME type of all formats. In those + # cases, content_type will be None. + f.content_type = Image.MIME.get(image.format) except Exception: # Pillow doesn't recognize it as an image. six.reraise(ValidationError, ValidationError( diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt index c8317924d9..55a8bc049e 100644 --- a/docs/ref/forms/fields.txt +++ b/docs/ref/forms/fields.txt @@ -690,13 +690,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 :ref:`bind the file data to the form `. + 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. Also, + ``UploadedFile.content_type`` will be updated with the image's content type + if Pillow can determine it, otherwise it will be set to ``None``. + .. 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. + The ``image`` and ``content_type`` attributes described in the last + paragraph were added. .. _Pillow: http://pillow.readthedocs.org/en/latest/ .. _Image: https://pillow.readthedocs.org/en/latest/reference/Image.html diff --git a/docs/releases/1.8.3.txt b/docs/releases/1.8.3.txt index c6745f92c3..ee525c9275 100644 --- a/docs/releases/1.8.3.txt +++ b/docs/releases/1.8.3.txt @@ -71,3 +71,6 @@ Bugfixes using UUID primary keys (:ticket:`24912`). * Fixed removing ``unique_together`` constraints on MySQL (:ticket:`24972`). + +* Fixed crash when uploading images with MIME types that Pillow doesn't detect, + such as bitmap, in ``forms.ImageField`` (:ticket:`24948`). diff --git a/tests/forms_tests/tests/filepath_test_files/1x1.bmp b/tests/forms_tests/tests/filepath_test_files/1x1.bmp new file mode 100644 index 0000000000..021d5fa928 Binary files /dev/null and b/tests/forms_tests/tests/filepath_test_files/1x1.bmp differ diff --git a/tests/forms_tests/tests/test_fields.py b/tests/forms_tests/tests/test_fields.py index 1d09b1a8b3..b082701c11 100644 --- a/tests/forms_tests/tests/test_fields.py +++ b/tests/forms_tests/tests/test_fields.py @@ -806,6 +806,26 @@ class FieldsTests(SimpleTestCase): self.assertEqual('PNG', uploaded_file.image.format) self.assertEqual('image/png', uploaded_file.content_type) + @skipIf(Image is None, "Pillow is required to test ImageField") + def test_imagefield_annotate_with_bitmap_image_after_clean(self): + """ + This also tests the situation when Pillow doesn't detect the MIME type + of the image (#24948). + """ + f = ImageField() + + img_path = os.path.dirname(upath(__file__)) + '/filepath_test_files/1x1.bmp' + with open(img_path, 'rb') as img_file: + img_data = img_file.read() + + img_file = SimpleUploadedFile('1x1.bmp', img_data) + img_file.content_type = 'text/plain' + + uploaded_file = f.clean(img_file) + + self.assertEqual('BMP', uploaded_file.image.format) + self.assertIsNone(uploaded_file.content_type) + # URLField ################################################################## def test_urlfield_1(self): @@ -1347,6 +1367,7 @@ class FieldsTests(SimpleTestCase): f.choices.sort() expected = [ ('/tests/forms_tests/tests/filepath_test_files/.dot-file', '.dot-file'), + ('/tests/forms_tests/tests/filepath_test_files/1x1.bmp', '1x1.bmp'), ('/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/fake-image.jpg', 'fake-image.jpg'),