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:
唯一的问题是缩略图没有被分配到新创建的缩略图的路径——它在数据库中是空的。我已经阅读了文档,看起来如果我将缩略图保存为save=True,应该可以解决我的问题:
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.
我不知道我做错了什么。
2 个解决方案
#1
6
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.
到def save()的末尾。我仍然不确定为什么会发生这种情况,但是我唯一的解释是save()本身将字段值持久化到数据库中,因此需要在最后执行它。
#2
2
Try pass the actual file contents instead of the SimpleUploadedFile object:
尝试传递实际的文件内容,而不是SimpleUploadedFile对象:
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
https://docs.djangoproject.com/en/dev/ files/file/#additional- on- files-attachedto -objects如何在Django中手动分配imagefield中以编程方式保存图像到Django imagefield
#1
6
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.
到def save()的末尾。我仍然不确定为什么会发生这种情况,但是我唯一的解释是save()本身将字段值持久化到数据库中,因此需要在最后执行它。
#2
2
Try pass the actual file contents instead of the SimpleUploadedFile object:
尝试传递实际的文件内容,而不是SimpleUploadedFile对象:
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
https://docs.djangoproject.com/en/dev/ files/file/#additional- on- files-attachedto -objects如何在Django中手动分配imagefield中以编程方式保存图像到Django imagefield