Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Saving an image manually to an ImageField field

The following code takes an image after it gets saved and makes a thumbnail out of it:

class Image(models.Model):
    image     = models.ImageField(upload_to='images')
    thumbnail = models.ImageField(upload_to='images/thumbnails', editable=False)

    def save(self, *args, **kwargs):
       super(Image, self).save(*args, **kwargs)
       if self.image:
           from PIL import Image as ImageObj
           from cStringIO import StringIO
           from django.core.files.uploadedfile import SimpleUploadedFile

           try:
               # thumbnail
               THUMBNAIL_SIZE = (160, 160)  # dimensions

               image = ImageObj.open(self.image)

               # Convert to RGB if necessary
               if image.mode not in ('L', 'RGB'): image = image.convert('RGB')

               # create a thumbnail + use antialiasing for a smoother thumbnail
               image.thumbnail(THUMBNAIL_SIZE, ImageObj.ANTIALIAS)

               # fetch image into memory
               temp_handle = StringIO()
               image.save(temp_handle, 'png')
               temp_handle.seek(0)

               # save it
               file_name, file_ext = os.path.splitext(self.image.name.rpartition('/')[-1])
               suf = SimpleUploadedFile(file_name + file_ext, temp_handle.read(), content_type='image/png')

               self.thumbnail.save(file_name + '.png', suf, save=False)
           except ImportError:
               pass

It's working fine, the original image + the thumbnail are both being uploaded, and image is being assigned the correct path.

The only problem is thumbnail is not being assigned the path of the newly created thumbnail - it's empty in the database. I have read the documentation, and it looks like if I save the thumbnail with save=True it should fix my problem:

self.thumbnail.save(file_name + '.png', suf, save=True)

However, doing this is raising the following:

Django Version: 1.3.1
Exception Type: IOError
Exception Value:    
cannot identify image file

I can't figure out what I'm doing wrong.

like image 921
Aziz Alfoudari Avatar asked Oct 25 '11 19:10

Aziz Alfoudari


2 Answers

I have solved my problem simply by moving:

super(Image, self).save(*args, **kwargs)

to the end of def save(). I'm still not certain why it's happening this way, but my only explanation is that save() itself is persisting fields values to the database and hence it needs to be executed at the very end.

like image 118
Aziz Alfoudari Avatar answered Sep 27 '22 20:09

Aziz Alfoudari


Try pass the actual file contents instead of the SimpleUploadedFile object:

self.thumbnail.save(file_name + '.png', temp_handle.read(), save=True)

https://docs.djangoproject.com/en/dev/ref/files/file/#additional-methods-on-files-attached-to-objects how to manually assign imagefield in Django Programmatically saving image to Django ImageField

like image 45
Timmy O'Mahony Avatar answered Sep 27 '22 20:09

Timmy O'Mahony