Commit 8b734722 authored by Petras Zdanavičius's avatar Petras Zdanavičius Committed by Tim Graham
Browse files

Fixed #23103 -- Annotated ImageField file with image and content_type attributes.

Thanks Jeremy Dunck for the suggestion and Nick Sanford for review.
parent 8c2b405b
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -659,8 +659,13 @@ class ImageField(FileField):
        try:
            # load() could spot a truncated JPEG, but it loads the entire
            # image in memory, which is a DoS vector. See #3848 and #18520.
            image = Image.open(file)
            # 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:
            # Pillow doesn't recognize it as an image.
            six.reraise(ValidationError, ValidationError(
+9 −0
Original line number Diff line number Diff line
@@ -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
    :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/
.. _Image: https://pillow.readthedocs.org/en/latest/reference/Image.html

``IntegerField``
~~~~~~~~~~~~~~~~
+6 −0
Original line number Diff line number Diff line
@@ -160,6 +160,12 @@ Forms
  :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.

* 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
^^^^^^^^^^^^^^^^^^^^

+150 B
Loading image diff...
+26 −1
Original line number Diff line number Diff line
@@ -31,12 +31,18 @@ import pickle
import re
import os
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.forms import (
    BooleanField, CharField, ChoiceField, ComboField, DateField, DateTimeField,
    DecimalField, EmailField, Field, FileField, FilePathField, FloatField,
    Form, forms, HiddenInput, IntegerField, MultipleChoiceField,
    Form, forms, HiddenInput, ImageField, IntegerField, MultipleChoiceField,
    NullBooleanField, NumberInput, PasswordInput, RadioSelect, RegexField,
    SplitDateTimeField, TextInput, Textarea, TimeField, TypedChoiceField,
    TypedMultipleChoiceField, URLField, ValidationError, Widget,
@@ -741,6 +747,24 @@ class FieldsTests(SimpleTestCase):
        # with here)
        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 ##################################################################

    def test_urlfield_1(self):
@@ -1262,6 +1286,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.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'),
            ('/tests/forms_tests/tests/filepath_test_files/real-text-file.txt', 'real-text-file.txt'),