ImageField width/height validation

1,132 views
Skip to first unread message

Giuliani Vito, Ivan

unread,
Mar 1, 2008, 1:20:55 PM3/1/08
to Django users
I need to check for an ImageField width/height in a model because I
want to force the uploaded image's dimensions to a fixed value of
620x250px.
I tried setting a [width/height]_field and running a custom validator
against those field but the validator doesn't get called (I suppose
that this happens because of "auto-generated" value of these fields).

Here follows the code I used, I'm doing something wrong?


class FImage(models.Model):
...
img = models.ImageField(upload_to='images', blank=False,
verbose_name=_("Image"),
width_field="img_width", height_field="img_height",
help_text=_("Image must be 620x250px large."))

img_width = models.PositiveIntegerField(editable=False,
validator_list=[custom_validator.IsEqualTo(620), ])
img_height = models.PositiveIntegerField(editable=False,
validator_list=[custom_validator.IsEqualTo(620), ])
...

and here's the IsEqualTo validator:

class IsEqualTo(object):
def __init__(self, equal_to, error_message=_("It's not equal to
the desidered value!")):
self.equal_to, self.error_message = equal_to, error_message

def __call__(self, field_data, all_data):
if field_data != self.equal_to:
raise validators.ValidationError, self.error_message

Regards,
Ivan

Michael Newman

unread,
Mar 1, 2008, 6:25:27 PM3/1/08
to Django users
You can't check the size of a image with python until the image is
actually uploaded. The best way to check before the file is uploaded
is with javascript. Sorry.

Giuliani Vito, Ivan

unread,
Mar 2, 2008, 3:41:06 AM3/2/08
to Django users
On Mar 2, 12:25 am, Michael Newman <newmani...@gmail.com> wrote:
> You can't check the size of a image with python until the image is
> actually uploaded. The best way to check before the file is uploaded
> is with javascript. Sorry.

Actually, validators are ran *after* that all the fields have been
uploaded (it doesn't matter if they're file fields or simple text
fields). The real problem is that the validator is not ran on the
img_height/img_width field I defined (I suppose because of the linking
with the ImageField), even if they're filled *before* than the model's
save method (you can easily notice this by overriding the save method
in your model and by printing these values). I don't know if this is
some kind of expected behaviour, but anyway I found a workaround to
this problem.

Here's the working code:


class FI(models.Model):
...

img = models.ImageField(upload_to='images', blank=False,
verbose_name=_("Image"),
validator_list=[custom_validators.ImageLarge(620, 250,
_("The image must be 620x250px large!")), ],
help_text=_("Image must be 620x250px large."))


And here follows the validator's code:


from django.utils.translation import gettext_lazy as _
from django.core import validators
import StringIO
from PIL import Image

class ImageLarge(object):
def __init__(self, width, height, error_message=_("The image isn't
as large as expected!")):
self.w, self.h, self.error_message = width, height,
error_message

def __call__(self, field_data, all_data):
im = Image.open(StringIO.StringIO(field_data['content']))
if im.size[0] != self.w or im.size[1] != self.h:
raise validators.ValidationError, self.error_message


Even if it isn't the most elegant solution, it works. The main issue
is that we store the *entire* image content in memory for processing
through PIL. For me it isn't a huge problem since the images will
never be bigger than ~700k, but could be a problem for someone else.
Additionally I don't know if it will still work when the #2070
ticket's patch [1] will be included (and I didn't checked with the
actual existing patch) since I didn't read carefully the ticket so I
don't know exactly how it works.

Regards,
Ivan


[1] http://code.djangoproject.com/ticket/2070
Reply all
Reply to author
Forward
0 new messages