How to validate Django ImageField dimensions

How to validate Django ImageField dimensions

May 3, 2021

Django framework makes storing image files against your database models easy via the ImageField field type. It does not however provide a way for you to validate the dimensions of this uploaded image.

This is of course important to do, otherwise your application will be hosting oversized images which could cause performance issues for end users.

In order to validate image dimensions at the model level we need to create a custom validator.

Here's the code for our validator:

from django.core.exceptions import ValidationError

def validate_minimum_size(width=None, height=None):
    def validator(image):
        error = False
        if width is not None and image.width < width:
            error = True
        if height is not None and image.height < height:
            error = True
        if error:
            raise ValidationError(
                [f'Size should be at least {width} x {height} pixels.']
            )

    return validator

And here's how we can use that in our `models.py` module:

from django.db import models

class ExampleModel(models.Model):
    avatar_image = models.ImageField(
        null=True,
        blank=True,
        validators=[validate_minimum_size(width=98, height=98)],
    )

When our model instance is saved this validator will be invoked and if the image is outside of our desired dimensions then an exception will be raised.

By using Django's built-in `ValidationError` errors will propagate all the way to the frontend of the application (if you're using Django forms linked to your templates).

If you're adding this to your project you may also want the tests ☑️

from unittest.mock import Mock
from myapp import validators

class TestValidateMinimumSize:
    def test_does_not_raise_when_image_meets_requirements(self):
        mock_image = Mock(width=10, height=10)
        validator = validators.validate_minimum_size(width=10, height=10)

        validator(image=mock_image)

    def test_raises_if_image_is_too_small(self):
        mock_image = Mock(width=9, height=9)
        validator = validators.validate_minimum_size(width=10, height=10)

        with pytest.raises(ValidationError):
            validator(image=mock_image)

Latest Articles

How to validate Django ImageField dimensions
How to use ipdb debugger with docker-compose
How to rename an existing Django application, the right way