tags:

views:

84

answers:

3
class MyModel(models.Model)
 image = models.FileField(upload_to="blagh blagh...")
 #more spam...

I have a file in memory and I want to save it via Django FileField save method, like this:

photo.image.save(name, buffer) # second arg should be django File

I've tried to use StringIO, but it doesn't extend django.core.files.File and thus doesn't implement method chunks(). I've wrapped it in a File object like that:

buffile = File(buffer, name) # first argument should be a file
photo.image.save(name, buffile)

But File methods use size and name fields of supplied file. StringIO doesn't define them. I've found this, but the link is dead

A: 

Use the Image class.

joel3000
I considered that, but then I would not use django mechanism for naming files (if a file with a given name exists, add underscore to the filename). And yes, I know, I could do that by myself and I could do that in other way, but It would be the best if I did that, like I described before.
joozek
A: 

If you've got a stream of bytes, which you'd like to save to a FileField/ImageField, here's some code that might help:

>>> from django.core.files.uploadedfile import InMemoryUploadedFile
>>> from cStringIO import StringIO
>>> buf = StringIO(data)  # `data` is your stream of bytes
>>> buf.seek(0, 2)  # Seek to the end of the stream, so we can get its length with `buf.tell()`
>>> file = InMemoryUploadedFile(buf, "image", "some_filename.png", None, buf.tell(), None)
>>> photo.image.save(file.name, file)  # `photo` is an instance of `MyModel`
>>> photo.image
<ImageFieldFile: ...>

Some notes:

  • You can make up whatever name you want for the image, but you'll probably want to keep the extension accurate
  • The second argument to InMemoryUploadedFile is the name of the field in your model, hence "image"

It's a little finnicky, but it gets the job done. Hopefully, the API will get cleaned up a bit more in 1.3/4.

Edit:
See Jason's answer for a much simpler way of doing this, though you'll still want to know the filename of the image.

elo80ka
Thanks, that was just what I was looking for :)
joozek
+2  A: 

You can use ContentFile instead of File

from django.core.files.base import ContentFile

photo.image.save(name, ContentFile(buffer))
Jason
Neat! This is so much simpler than my solution...+1
elo80ka