[1.11.x] Fixed #28242 -- Moved ImageField file extension validation to the form field.
Backport of a0c07d77fc
from master
This commit is contained in:
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):
|
||||
|
|
Loading…
Reference in New Issue