FileSystemStorage content vs PIL Image

106 views
Skip to first unread message

Donn

unread,
Jan 4, 2009, 5:51:03 PM1/4/09
to django...@googlegroups.com
Hi,
I am stuck on the interface between a PIL Image and a
FilesystemStorage 'content' object.

I can: img = Image.open(content)
But how do I pass 'img' back to Django for saving?

My short class is pasted at end. The problem reported stems from the line:
name=super(CustomImageStorage,self).save(name,img)

It barfs in PIL saying:
Exception Type: AttributeError
Exception Value:

chunks

Exception Location: /usr/lib/python2.5/site-packages/PIL/Image.py in
__getattr__, line 493


I dir() the content and img objects and sure enough, img has no 'chunks'
attribute.

Anyway, I can always use img.save(path) but wanted to keep the image in memory
and not touch ground with it.

Any ideas?
\d

Code:
class CustomImageStorage( FileSystemStorage ):
def __init__(self, location, base_url, makethumbs=False,dropshadow=None):
super(CustomImageStorage,self).__init__(location=location,base_url=base_url)
self._makethumbs = makethumbs
self._dropshadow = dropshadow

def get_available_name( self, name ):
self.delete(name)
return name

def save(self, name, content ):
content.seek(0)
img = Image.open(content)
if self._dropshadow:
img = dropShadow(img, background = self._dropshadow['background'],
shadow = self._dropshadow['shadow'],
offset = self._dropshadow['offset'],
iterations = self._dropshadow['iterations'],
border = self._dropshadow['border']
)
if self._makethumbs:
try:
thumb = img.copy()
fpaf = self.thumbPath(name)
thumb.thumbnail((64,64),Image.ANTIALIAS)
thumb.save( fpaf )
except:
pass # some damn error.
img.seek(0) # Random attempt at a fix
name = super( CustomImageStorage,self).save(name,img) # was content
return name

def delete( self, name):
super(CustomImageStorage,self).delete(name)
if self._makethumbs:
# Now to remove the thumbnail too.
try:
fpaf = self.thumbPath(name)
os.unlink( fpaf )
except:
pass # Can't delete it... whatever.

def thumbPath( self, name ):
return os.path.join(self.location,'djanthumbs', name)

Eric Abrahamsen

unread,
Jan 4, 2009, 8:51:26 PM1/4/09
to django...@googlegroups.com
"Content" in this case is supposed to be an instance of
django.core.files.File, not raw data (see http://docs.djangoproject.com/en/dev/ref/files/file/)
. It's the File object that has the missing "chunks" attribute. At the
very least, try instantiating a File object within your save method,
write the img data to that file object, and the pass the file to the
call to super().save(). Maybe there will be to it than just that, but
that's a good place to start.

Yours,
Eric

Eric Abrahamsen

unread,
Jan 4, 2009, 10:15:27 PM1/4/09
to django...@googlegroups.com

On Jan 5, 2009, at 6:51 AM, Donn wrote:

>
On second thought, you should probably be writing the img back into
the original "content" variable (which points to a File object), as
that object might already have relevant attributes set...

E

Donn

unread,
Jan 5, 2009, 2:48:18 AM1/5/09
to django...@googlegroups.com
On Monday, 05 January 2009 05:15:27 Eric Abrahamsen wrote:
> On second thought, you should probably be writing the img back into  
> the original "content" variable (which points to a File object), as  
> that object might already have relevant attributes set...
I guess that's what I was asking: how does one do that?
I will go look at Storage objects in the docs, it's early here ;)

Thanks,
\d

Malcolm Tredinnick

unread,
Jan 5, 2009, 2:44:37 AM1/5/09
to django...@googlegroups.com

This isn't going to be too helpful, directly, but I'll note that you
aren't being particularly dense for not understanding this stuff.
Customising and tweaking the file upload and internals handling is
possible, but it's not particularly simple or clearly explained,
currently. At some point we need to do another pass over the
documentation to add in a more holistic story for the fine-grained
tweaking.

Basically, hang in there and be prepared to experiment a bit and
possibly read some source code. Take notes as you go.

Regards,
Malcolm


Donn

unread,
Jan 5, 2009, 3:29:54 AM1/5/09
to django...@googlegroups.com
On Monday, 05 January 2009 09:44:37 Malcolm Tredinnick wrote:
> Basically, hang in there and be prepared to experiment a bit and
> possibly read some source code. Take notes as you go

Heh -- thanks for that! It does lift my spirits somewhat. I have been planning
to write a short tut on how to manage uploads, so I will certainly be keeping
notes.

\d

Donn

unread,
Jan 5, 2009, 6:47:08 AM1/5/09
to django...@googlegroups.com
On Monday, 05 January 2009 00:51:03 Donn wrote:
> I am stuck on the interface between a PIL Image and a
> FilesystemStorage 'content' object.
>
> I can: img = Image.open(content)
> But how do I pass 'img' back to Django for saving?

I have some kind of working example now. I won't say I savvy it properly, but
it's a case of finding objects that FileSystemStorage.save will accept.

This object needs a 'chunks' attribute. It's raw data must also be in binary
format. So, I need to go from a PIL 'img' out to this magical object:

You need this class
from django.core.files.base import ContentFile

And this:
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

In the code, insert:

#Make a thing to hold our data
o = StringIO()

#convert the image to a binary file-like memory object
img.save(o,'PNG')

# We NEED this object because it has 'chunks'
content = ContentFile(o.getvalue())

# Now the content is accepted.
# CutsomImageStorage is my FileSystemStorage subclass, see OP.
super( CustomImageStorage,self).save(name, content)

HTH; any corrections for sheer stupidity? :)

\d

Eric Abrahamsen

unread,
Jan 5, 2009, 7:00:16 AM1/5/09
to django...@googlegroups.com
Instead of instantiating a new object, have you tried writing back to
the original "content" file object that was passed in as a parameter
to save? It's got a write method:

content.write(o.getvalue())
super(CustomImageStorage,self).save(name, content)

That might avoid causing new problems...

E

Donn

unread,
Jan 5, 2009, 7:30:18 AM1/5/09
to django...@googlegroups.com, Eric Abrahamsen
On Monday, 05 January 2009 14:00:16 Eric Abrahamsen wrote:
> content.write(o.getvalue())
> super(CustomImageStorage,self).save(name, content)

That gives:
'InMemoryUploadedFile' object has no attribute '_mode'
Exception
Location: /usr/lib/python2.5/site-packages/django/core/files/base.py in
_get_mode, line 39

I recall getting this mode error and went past it to my eventual solution. But
I'd like to know if it's kosher or crazy.

\d

A Melé

unread,
Jan 5, 2009, 10:50:09 AM1/5/09
to Django users
Donn, take a look at django-thumbs source code, it integrates PIL and
SotrageBackend: http://code.google.com/p/django-thumbs/source/browse/trunk/thumbs.py
I hope the code helps you.


Regards,

Antonio Melé
http://django.es/blog/

Donn

unread,
Jan 5, 2009, 11:09:25 AM1/5/09
to django...@googlegroups.com, A Melé
On Monday, 05 January 2009 17:50:09 A Melé wrote:
> Donn, take a look at django-thumbs source code
Many thanks -- it looks familiar now :)

\d

Reply all
Reply to author
Forward
0 new messages