Kaydet (Commit) a0c07d77 authored tarafından Manatsawin Hanmongkolchai's avatar Manatsawin Hanmongkolchai Kaydeden (comit) Tim Graham

Fixed #28242 -- Moved ImageField file extension validation to the form field.

üst 6bb3b2bf
...@@ -6,7 +6,6 @@ from django.core import checks ...@@ -6,7 +6,6 @@ from django.core import checks
from django.core.files.base import File from django.core.files.base import File
from django.core.files.images import ImageFile from django.core.files.images import ImageFile
from django.core.files.storage import default_storage 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 import signals
from django.db.models.fields import Field from django.db.models.fields import Field
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
...@@ -355,7 +354,6 @@ class ImageFieldFile(ImageFile, FieldFile): ...@@ -355,7 +354,6 @@ class ImageFieldFile(ImageFile, FieldFile):
class ImageField(FileField): class ImageField(FileField):
default_validators = [validate_image_file_extension]
attr_class = ImageFieldFile attr_class = ImageFieldFile
descriptor_class = ImageFileDescriptor descriptor_class = ImageFileDescriptor
description = _("Image") description = _("Image")
......
...@@ -591,6 +591,7 @@ class FileField(Field): ...@@ -591,6 +591,7 @@ class FileField(Field):
class ImageField(FileField): class ImageField(FileField):
default_validators = [validators.validate_image_file_extension]
default_error_messages = { default_error_messages = {
'invalid_image': _( 'invalid_image': _(
"Upload a valid image. The file you uploaded was either not an " "Upload a valid image. The file you uploaded was either not an "
......
...@@ -58,3 +58,7 @@ Bugfixes ...@@ -58,3 +58,7 @@ Bugfixes
* Fixed a regression where ``file_move_safe()`` crashed when moving files to a * Fixed a regression where ``file_move_safe()`` crashed when moving files to a
CIFS mount (:ticket:`28170`). 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 ...@@ -327,6 +327,7 @@ Models
* :class:`~django.db.models.ImageField` now has a default * :class:`~django.db.models.ImageField` now has a default
:data:`~django.core.validators.validate_image_file_extension` validator. :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 * Added support for time truncation to
:class:`~django.db.models.functions.datetime.Trunc` functions. :class:`~django.db.models.functions.datetime.Trunc` functions.
......
...@@ -2,7 +2,7 @@ import os ...@@ -2,7 +2,7 @@ import os
import unittest import unittest
from django.core.files.uploadedfile import SimpleUploadedFile 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.test import SimpleTestCase
try: try:
...@@ -55,3 +55,12 @@ class ImageFieldTest(SimpleTestCase): ...@@ -55,3 +55,12 @@ class ImageFieldTest(SimpleTestCase):
self.assertIsNone(uploaded_file.content_type) self.assertIsNone(uploaded_file.content_type)
finally: finally:
Image.register_mime(BmpImageFile.format, 'image/bmp') 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)
...@@ -2,7 +2,7 @@ import os ...@@ -2,7 +2,7 @@ import os
import shutil import shutil
from unittest import skipIf 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 import File
from django.core.files.images import ImageFile from django.core.files.images import ImageFile
from django.test import TestCase from django.test import TestCase
...@@ -130,12 +130,6 @@ class ImageFieldTests(ImageFieldTestMixin, TestCase): ...@@ -130,12 +130,6 @@ class ImageFieldTests(ImageFieldTestMixin, TestCase):
self.assertEqual(hash(p1_db.mugshot), hash(p1.mugshot)) self.assertEqual(hash(p1_db.mugshot), hash(p1.mugshot))
self.assertIs(p1_db.mugshot != p1.mugshot, False) 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): def test_instantiate_missing(self):
""" """
If the underlying file is unavailable, still create instantiate the If the underlying file is unavailable, still create instantiate the
......
...@@ -192,6 +192,17 @@ try: ...@@ -192,6 +192,17 @@ try:
def __str__(self): def __str__(self):
return self.description 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: except ImportError:
test_images = False test_images = False
......
...@@ -32,7 +32,7 @@ from .models import ( ...@@ -32,7 +32,7 @@ from .models import (
) )
if test_images: if test_images:
from .models import ImageFile, OptionalImageFile from .models import ImageFile, OptionalImageFile, NoExtensionImageFile
class ImageFileForm(forms.ModelForm): class ImageFileForm(forms.ModelForm):
class Meta: class Meta:
...@@ -44,6 +44,11 @@ if test_images: ...@@ -44,6 +44,11 @@ if test_images:
model = OptionalImageFile model = OptionalImageFile
fields = '__all__' fields = '__all__'
class NoExtensionImageFileForm(forms.ModelForm):
class Meta:
model = NoExtensionImageFile
fields = '__all__'
class ProductForm(forms.ModelForm): class ProductForm(forms.ModelForm):
class Meta: class Meta:
...@@ -2461,6 +2466,19 @@ class FileAndImageFieldTests(TestCase): ...@@ -2461,6 +2466,19 @@ class FileAndImageFieldTests(TestCase):
self.assertEqual(instance.image.name, 'foo/test4.png') self.assertEqual(instance.image.name, 'foo/test4.png')
instance.delete() 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): class ModelOtherFieldTests(SimpleTestCase):
def test_big_integer_field(self): def test_big_integer_field(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment