ImageField validation

In my model I defined and ImageField()

image = models.ImageField(upload_to='images/%Y/%m/%d/', blank=True, null=True)

I want to validate the uploaded image on:
extensions = (‘gif’, ‘jpg’, ‘jpeg’, ‘png’)
dimensions = (360, 80))
size = (32*1024)

I had a look at validate_image_file_extension but that only validates the extension. Is there a validator that validates all three.

I saw validators being defined in models.py, is that the best place or should I put the validator in views.py or forms.py.

Kind regards,

Johanna

1 Like

It kinda depends upon what you want to have happen if the submitted file is not valid. I’d be inclined to validate the image in the form - the earliest possible point, and before it gets saved.

I’d probably write a custom file handler* to allow me to access the data before it gets written to a file and then use Pillow to examine that image to determine its dimensions. (The file object provides access to verify the size. So I’d probably check the extension and size first, before calling Pillow to identify the dimensions.)

(* Also see Custom upload handlers)

I followed the links you provided, and read through a lot of ImageField() and validators documentation.

I thought the easiest way to validate an image would be making use of the attributes in the class ImageField()

class ImageField(upload_to=None, height_field=None, width_field=None, max_length=100, **options)

In models.py I have:

from PIL import Image
from django.core.validators import FileExtensionValidator
from config.settings import ALLOWED_IMAGE_EXTENSIONS

class Logo(models.Model):
    node = models.OneToOneField(Node, on_delete=models.CASCADE, primary_key=True, related_name='logos', related_query_name='logo')
    image = models.ImageField(
        upload_to='images/%Y/%m/%d/',
        width_field='240',
        height_field='120',
        max_length=64*1024,
        validators=[FileExtensionValidator(allowed_extensions=ALLOWED_IMAGE_EXTENSIONS)])

When I upload an image I get an AttributeError:

Exception Type:	AttributeError
Exception Value:	
'Logo' object has no attribute '240'
Exception Location:	/Users/annet/Documents/project/venv/lib/python3.10/site-packages/django/db/models/fields/files.py, line 475, in update_dimension_fields

Obviously my understanding of the attributes is wrong, what did I miss reading the documentation?

Quoting from the docs for the model ImageField.width_field:

Name of a model field which will be auto-populated with the width of the image each time the model instance is saved.

That attribute identifies a field to be populated by Django when the model is saved.

In other words, in your image field definition, you would have width_field = image_width, and then another field in your model: image_width = IntegerField(). Similarly, you would have a height field defined and reference that field name in the height_field attribute of the ImageField.

Note that these are populated when the model instance is saved, and so they don’t provide any capability for you to check them before then. (They also don’t define or create any limitation on those values. Any defaults defined in those fields are going to be overwritten by the actual value obtained from the image.)