Last active
December 11, 2024 08:47
-
-
Save jacoor/1dfbd40497d4125f6888384bf61c845a to your computer and use it in GitHub Desktop.
Django image validator example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
avatar = models.ImageField( | |
upload_to=user_avatar_path, | |
null=True, | |
blank=True, | |
default=None, | |
validators=[ | |
FileExtensionValidator(allowed_extensions=["jpg", "jpeg", "png"]), | |
validate_image_file, # Reusable image validation | |
], | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pytest | |
from django.core.exceptions import ValidationError | |
from io import BytesIO | |
from PIL import Image | |
from users.validators import validate_image_file # Replace 'your_app' with your app name | |
def create_test_image(format="JPEG", size=(100, 100), color=(255, 0, 0)): | |
""" | |
Helper function to create an in-memory test image. | |
""" | |
img = Image.new("RGB", size, color) | |
image_io = BytesIO() | |
img.save(image_io, format=format) | |
image_io.seek(0) | |
return image_io | |
@pytest.mark.parametrize("image_format", ["JPEG", "PNG"]) | |
def test_valid_image_formats(image_format): | |
""" | |
Test that valid image formats pass the validation. | |
""" | |
image_file = create_test_image(format=image_format) | |
try: | |
validate_image_file(image_file) | |
except ValidationError: | |
pytest.fail(f"Validation failed for valid {image_format} image.") | |
def test_invalid_image_format(): | |
""" | |
Test that an invalid image format raises a ValidationError. | |
""" | |
image_file = BytesIO(b"not-a-real-image") | |
with pytest.raises(ValidationError, match="Uploaded file is not a valid image."): | |
validate_image_file(image_file) | |
def test_image_with_unsupported_format(): | |
""" | |
Test that an image with an unsupported format raises a ValidationError. | |
""" | |
image_file = create_test_image(format="BMP") | |
with pytest.raises(ValidationError, match="Only JPEG and PNG image formats are supported."): | |
validate_image_file(image_file) | |
def test_image_too_large_dimensions(): | |
""" | |
Test that an image exceeding the maximum dimensions raises a ValidationError. | |
""" | |
max_width, max_height = 1920, 1080 | |
image_file = create_test_image(size=(max_width + 1, max_height + 1)) | |
with pytest.raises(ValidationError) as excinfo: | |
validate_image_file(image_file) | |
# Assert the error message matches the new, consistent message | |
assert "Image is too large." in excinfo.value.messages[0] | |
def test_valid_image_dimensions(): | |
""" | |
Test that an image within the valid dimensions passes the validation. | |
""" | |
max_width, max_height = 1920, 1080 | |
image_file = create_test_image(size=(max_width, max_height)) | |
try: | |
validate_image_file(image_file) | |
except ValidationError: | |
pytest.fail("Validation failed for an image within valid dimensions.") | |
def test_corrupted_image_file(): | |
""" | |
Test that a corrupted image file raises a ValidationError. | |
""" | |
image_file = create_test_image() | |
# Corrupt the image file by truncating its content | |
corrupted_image_file = BytesIO(image_file.read()[:10]) | |
with pytest.raises(ValidationError, match="Uploaded file is not a valid image."): | |
validate_image_file(corrupted_image_file) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.core.exceptions import ValidationError | |
from django.utils.translation import gettext_lazy as _ | |
from PIL import Image | |
import os | |
def validate_image_file(image_file): | |
""" | |
Validator to ensure the uploaded file is a valid image. | |
""" | |
from PIL import Image | |
from django.core.exceptions import ValidationError | |
from django.utils.translation import gettext_lazy as _ | |
try: | |
img = Image.open(image_file) | |
img.verify() | |
except (IOError, SyntaxError): | |
raise ValidationError(_("Uploaded file is not a valid image.")) | |
img = Image.open(image_file) # Required after .verify() | |
allowed_formats = ["JPEG", "PNG"] | |
if img.format not in allowed_formats: | |
raise ValidationError(_("Only JPEG and PNG image formats are supported.")) | |
max_width, max_height = 1920, 1080 | |
width, height = img.size | |
if width > max_width or height > max_height: | |
raise ValidationError( | |
_(f"Image is too large. Maximum resolution is {max_width}x{max_height} pixels.") | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment