Search code examples
djangorackspace-clouddjango-models

How can I programatically save an Image to an ImageField using Django-Cumulus?


I am using Django-Cumulus to store images to Rackspace's Cloudfiles platform.

I want to, dynamically, manipulate my images and save them as a new ImageField for my Model. For example, I have a Photo model with these ImageFields: image, thumb_256x256

In my Form's save() method, I am letting the user specify the cropping locations (using JCrop).

Anyways, I know how to grab the existing image file that the user uploaded. I also know how to apply manipulations with PIL. The problem I'm running into is creating a new Rackspace File and writing to it.

I keep getting the exception "NoSuchObject".

Here's some example code:

def save(self, commit=True):
    """ Override the Save method to create a thumbnail of the image. """
    m = super(PhotoUpdateForm, self).save(commit=False)

    image = Image.open(m.image.file)
    image.thumbnail((256,256), Image.ANTIALIAS)
    thumb_io = CloudFilesStorageFile(storage=CLOUDFILES_STORAGE, name='foo/bar/test.jpg')
    image.save(thumb_io.file, format='JPEG')

Also, once I get to this point -- what's the best way of setting this image to the model's other ImageField? (m.thumb_256x256 in my case)

Thanks in advanced!

Update: The name of the actual Cloudfiles Django app I'm using is "django-cumulus"


Solution

  • Here is a temporary solution. I'm having an issue with setting the new filename properly. It simply appends a _X to the filename. So for example, somefilename.jpg becomes somefilename_1.jpg whenever I save a new version.

    This code is a bit ugly but does get the job done. It creates a cropped version of the image and will also generate a thumbnail if needed.

    def save(self, commit=True):
        """ Override the Save method to create a thumbnail of the image. """
        m = super(PhotoUpdateForm, self).save(commit=False)
    
        # Cropped Version
        if set(('x1', 'x2', 'y1', 'y2')) <= set(self.cleaned_data):
            box = int(self.cleaned_data['x1']), \
                  int(self.cleaned_data['y1']), \
                  int(self.cleaned_data['x2']), \
                  int(self.cleaned_data['y2'])
            image = Image.open(m.image.file)
            image = image.crop(box)
            temp_file = NamedTemporaryFile(delete=True)
            image.save(temp_file, format="JPEG")
            m.image.save("image.jpg", File(temp_file))
            cropped = True # Let's rebuild the thumbnail
    
        # 256x256 Thumbnail
        if not m.thumb_256x256 or cropped:
            if not image:
                image = Image.open(m.image.file)
            image.thumbnail((256,256), Image.ANTIALIAS)
            temp_file = NamedTemporaryFile(delete=True)
            image.save(temp_file, format="JPEG")
            m.thumb_256x256.save("thumbnail.jpg", File(temp_file))
    
        if commit: m.save()
        return m