Reputation: 2589
I'm trying to resize an image while saving an instance of my model.
class Picture(models.Model):
image_file = models.ImageField(upload_to="pictures")
thumb_file = models.ImageField(upload_to="pictures", editable=False)
def save(self, force_insert=False, force_update=False):
image_object = Image.open(self.image_file.path)
#[...] nothing yet
super(Picture, self).save(force_insert, force_update)
The problem is that self.image_file.path does not exist before the model is being saved. It returns a correct path, but the image is not there yet. Since there is no image, I can't open it in PIL for resize.
I want to store the thumbnail in thumb_file (another ImageField), so I need do the processing before saving the model.
Is there a good way to open the file (maybe get the tmp image object in memory) or do I have to save the whole model first, resize and then save again ?
Upvotes: 5
Views: 5039
Reputation: 1450
On your model save
method the field value will be a valid FileField
or ImageFileField
in the case of an ImageField
. This django class implements the object file interface (i.e read
, write
) and it works even before the file is saved with your model, so you can use it as the parameter to PIL.Image.open
:
class Picture(models.Model):
image_file = models.ImageField(upload_to="pictures")
thumb_file = models.ImageField(upload_to="pictures", editable=False)
def save(self, force_insert=False, force_update=False):
img = Image.open(self.image_file)
# work with img, is an Image object
super(Picture, self).save(force_insert, force_update)
This works on django >= 1.5
.
Upvotes: 0
Reputation: 508
I used this snippet:
import Image
def fit(file_path, max_width=None, max_height=None, save_as=None):
# Open file
img = Image.open(file_path)
# Store original image width and height
w, h = img.size
# Replace width and height by the maximum values
w = int(max_width or w)
h = int(max_height or h)
# Proportinally resize
img.thumbnail((w, h), Image.ANTIALIAS)
# Save in (optional) 'save_as' or in the original path
img.save(save_as or file_path)
return True
And in models:
def save(self, *args, **kwargs):
super(Picture, self).save(*args, **kwargs)
if self.image:
fit(self.image_file.path, settings.MAX_WIDTH, settings.MAX_HEIGHT)
Upvotes: 1
Reputation: 5580
Maybe you can open the file directly and pass the resulting file handle to Image.open
:
image_object = Image.open(self.image_file.open())
Sorry, I can't test that now.
Upvotes: 0