PIL issue opening an image file

853 views
Skip to first unread message

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 8:49:37 AM11/26/10
to django...@googlegroups.com
Hi all,

I have a Photo model which should take an image, generate a thumbnail and save both the original and the thumbnail images. I registered the model in the admin site, but when I select an image to upload and click 'Save', I get an error as follows:

Request Method:     POST
Request URL:     http://127.0.0.1:8000/admin/browse/photo/add/
Django Version:     1.2.3
Exception Type:     IOError
Exception Value:    

[Errno 2] No such file or directory: u'Lloyd.png'

Exception Location:     C:\Python26\lib\site-packages\PIL\Image.py in open, line 1952
Python Executable:     C:\Python26\python.exe
Python Version:     2.6.5

The model looks like this (the line where the error occurs is highlighted):

class Photo(models.Model):
     """
     An avatar for a site member
     """
     title =                       models.CharField(max_length=50)
     photo =                       models.ImageField(upload_to='photos/')
     thumbnail =                   models.ImageField(upload_to='thumbnails/', editable=False)

     def save(self):
          from PIL import Image
          from cStringIO import StringIO
          from django.core.files.uploadedfile import SimpleUploadedFile

          # Set our max thumbnail size in a tuple (max width, max height)
          THUMBNAIL_SIZE = (65, 65)

          # Open original photo which we want to thumbnail using PIL's Image
          # object
          image = Image.open(self.photo.name)

          # Convert to RGB if necessary
          # Thanks to Limodou on DjangoSnippets.org
          # http://www.djangosnippets.org/snippets/20/
          if image.mode not in ('L', 'RGB'):
               image = image.convert('RGB')

          # We use our PIL Image object to create the thumbnail, which already
          # has a thumbnail() convenience method that contrains proportions.
          # Additionally, we use Image.ANTIALIAS to make the image look better.
          # Without antialiasing the image pattern artifacts may result.
          image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)

          # Save the thumbnail
          temp_handle = StringIO()
          image.save(temp_handle, 'png')
          temp_handle.seek(0)

          # Save to the thumbnail field
          suf = SimpleUploadedFile(os.path.split(self.photo.name)[-1],
               temp_handle.read(), content_type='image/png')
          self.thunbnail.save(suf.name+'.png', suf, save=False)

          # Save this photo instance
          super(Photo, self).save()

          class Admin:
               pass

          def __str__(self):
               return self.title

What could the issue be? Any ideas welcome.

Thanks.
--
Regards,
Sithembewena Lloyd Dube
http://www.lloyddube.com

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 9:03:52 AM11/26/10
to django...@googlegroups.com
I found the issue: it is the path to the image. When I change the problem line to

image = Image.open(os.path.realpath('C:\Users\Lloyd\Desktop\Lloyd.png'))

it works, but I cannot hard code the path and I cannot predict where the user will try to upload a file from. Isn't there a way to dynamically get the path from the file upload dialogue where the user browses to it and selects it?

Thanks...

Daniel Roseman

unread,
Nov 26, 2010, 9:14:46 AM11/26/10
to Django users
On Nov 26, 2:03 pm, Sithembewena Lloyd Dube <zebr...@gmail.com> wrote:
> I found the issue: it is the path to the image. When I change the problem
> line to
>
> image = Image.open(os.path.realpath('C:\Users\Lloyd\Desktop\Lloyd.png'))
>
> it works, but I cannot hard code the path and I cannot predict where the
> user will try to upload a file from. Isn't there a way to dynamically get
> the path from the file upload dialogue where the user browses to it and
> selects it?
>
> Thanks...

Why were you using photo.name as the path in the first place?
photo.path stores the full path to the image, as noted in the
documentation:
http://docs.djangoproject.com/en/1.2/ref/files/file/
--
DR.

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 9:33:59 AM11/26/10
to django...@googlegroups.com
Thanks Daniel,

Using photo.path causes it to try to find the image in my MEDIA_ROOT, which is not what I need. I need a way to get the path from the image upload dialogue as encircled in the attached image.

The image is currently on my desktop and not in my media root and I need to get the desktop path.

Thanks!

Lloyd


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

photo_upload.png

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 9:37:07 AM11/26/10
to django...@googlegroups.com
If I was handling the photo in a view, I'm sure I could get the path information out of request.FILES['filename'] - but I am trying to upload it in a model.

Regards,
Lloyd

bruno desthuilliers

unread,
Nov 26, 2010, 9:50:03 AM11/26/10
to Django users


On 26 nov, 15:03, Sithembewena Lloyd Dube <zebr...@gmail.com> wrote:
> I found the issue: it is the path to the image. When I change the problem
> line to
>
> image = Image.open(os.path.realpath('C:\Users\Lloyd\Desktop\Lloyd.png'))
>
> it works,

Well, kinda... accidentally...

> but I cannot hard code the path and I cannot predict where the
> user will try to upload a file from.

That's not exactly the problem, but the mere fact you think you could
solve your problem that way says a lot about your misunderstanding of
the HTTP protocol.


> Isn't there a way to dynamically get
> the path from the file upload dialogue where the user browses to it and
> selects it?

What would you do with this information ? Do you really think the
server on which your application will be deployed will have any access
to the client's filesystem ???

bruno desthuilliers

unread,
Nov 26, 2010, 9:52:31 AM11/26/10
to Django users
On 26 nov, 15:33, Sithembewena Lloyd Dube <zebr...@gmail.com> wrote:
> Thanks Daniel,
>
> Using photo.path causes it to try to find the image in my MEDIA_ROOT, which
> is not what I need.

Yes it is.

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 10:13:10 AM11/26/10
to django...@googlegroups.com
Well, Bruno, if I knew exactly how to solve this I wouldn't be sitting here taking your snooty remarks, would I? I am asking because I do not know how to go about it.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 10:13:22 AM11/26/10
to django...@googlegroups.com
Thanks for nothing.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 10:16:28 AM11/26/10
to django...@googlegroups.com
Bruno, the file being uploaded has nothing to do with the deployment server. When you edit your Google profile to change your avatar, does the file upload dialogue browse a Google server?


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Daniel Roseman

unread,
Nov 26, 2010, 10:29:57 AM11/26/10
to Django users
On Nov 26, 3:16 pm, Sithembewena Lloyd Dube <zebr...@gmail.com> wrote:
> Bruno, the file being uploaded has nothing to do with the deployment server.
> When you edit your Google profile to change your avatar, does the file
> upload dialogue browse a Google server?

No. But that has nothing whatever to do with the problem you are
experiencing.

At the point you are calling the save() method, the file has *already*
been uploaded. There is absolutely *no way* for Python code running on
the server to access files on your machine. (Can you imagine the
security implications if that were possible?)
--
DR.

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 10:44:19 AM11/26/10
to django...@googlegroups.com
Thanks Daniel, makes sense. I gather that what Bruno meant to say on his soapbox was that the file is in the HTTP request object and can/ should not be accessible from the hard disk?

I was familiar with that, as the file upload dialogue does the job of reading the file off the disk and into memory.

So I see where I went wrong :) I was trying to read the file off the disk. I'll see if I can manipulate the file in a view, where I have access to the request object.

Is that the gist of the problem?

Thanks Daniel!


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Tom Evans

unread,
Nov 26, 2010, 10:55:12 AM11/26/10
to django...@googlegroups.com
On Fri, Nov 26, 2010 at 3:44 PM, Sithembewena Lloyd Dube
<zeb...@gmail.com> wrote:
> Thanks Daniel, makes sense. I gather that what Bruno meant to say on his
> soapbox was that the file is in the HTTP request object and can/ should not
> be accessible from the hard disk?
>
> I was familiar with that, as the file upload dialogue does the job of
> reading the file off the disk and into memory.
>
> So I see where I went wrong :) I was trying to read the file off the disk.
> I'll see if I can manipulate the file in a view, where I have access to the
> request object.
>
> Is that the gist of the problem?
>
> Thanks Daniel!
>

Not really.

1) User chooses file from disk
2) Browser reads file from disk, and generates POST request
3) Django receives POST request, and generates temporary file to store
received POST data
4) Django model form processes request, and moves temporary file into
the location specified by upload_to attribute on model field
5) You save the model instance, which puts us into the save() method,
where you want to create a thumbnail of the file

At this point, the full size image is on disk, in
os.path.join(settings.MEDIA_ROOT, instance.file_field.path). You want
to read that image in, create a django.core.files.File (or subclass)
instance for the thumbnailed image, and assign it to the thumbnail
field on the model.

Cheers

Tom

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 10:58:07 AM11/26/10
to django...@googlegroups.com
Thanks for breaking this down, Tom. I'll play around with it and see if I'm grasping this.

Regards,
Lloyd


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 2:07:18 PM11/26/10
to django...@googlegroups.com
So, I am making headway. Thanks to the gentlemen who nudged me onto the right path.

Quick word to Bruno Desthuilliers: while I appreciate that you have greater experience and might find others' endeavours ridiculous, you could be more helpful and respectful in your tone. Do you see a difference between your response and that of Tom Evans, for example? There is a civilised way to disagree.

This was not the first time that you and I have had something of a spat regarding your demeanour on this mailing list. The last time, you attacked a total novice to Django with the same air of wanton condescension -and worse, you condescended to Kaste (an experienced Django user) who was trying to come to the aid of said newbie.

This is a place where people  'fraternise', and mostly the goal of it all is to enlighten those that need to be enlightened. There is *absolutely* no reason to be uncouth about it. You were also once devoid of comprehension, and you gradually attained it, in no small part thanks to others' patience and advice.

Regards,
Lloyd

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 2:08:10 PM11/26/10
to django...@googlegroups.com
Kate, that was...

Steve Holden

unread,
Nov 26, 2010, 2:07:59 PM11/26/10
to django...@googlegroups.com
On 11/26/2010 9:58 AM, Sithembewena Lloyd Dube wrote:
> Thanks for breaking this down, Tom. I'll play around with it and see if
> I'm grasping this.

For the record, while it might have seemed to you that Bruno was being
"snooty", in fact he was probably (I have no direct evidence) simply
crediting you with more knowledge than you actually had.

Misunderstandings can be frustrating, and we all give in to the
frustration sometimes.

regards
Steve
--
DjangoCon US 2011 Portland, OR: September 6-8 http://djangocon.us/

Sithembewena Lloyd Dube

unread,
Nov 26, 2010, 2:19:14 PM11/26/10
to django...@googlegroups.com
@Steve, very well. I concede. It's just that it was not the first time I thought he could be more respectful in his approach. He has acknowledged and apologised for this type of behaviour previously. My concern is that those types of unhelpful responses could lead to newcomers feeling that this place is of no use other than to humiliate them. Also, I am certainly not one to be dressed down, no matter how stupid I might have been. Make me understand my mistake, but do not get onto a high horse about it. Then, we will co-exist just fine.

Regards,
Lloyd


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Reply all
Reply to author
Forward
0 new messages