I am having trouble putting together two ideas, resizing an image from models.ImageField
(which works fine if I don't try to also upload to my Amazon S3 bucket) and uploading an image to my Amazon S3 bucket).
我无法将两个想法放在一起,从models.ImageField调整图像大小(如果我不尝试上传到我的Amazon S3存储桶,它可以正常工作)并将图像上传到我的Amazon S3存储桶中。
My model:
我的模特:
from django.db import models
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
from django.core.files.storage import default_storage as storage
import datetime
from PIL import Image
import math
class Artwork(models.Model):
title = models.CharField(max_length=200)
# other fields...
full_image_large = models.ImageField(storage=S3BotoStorage(location='img'))
full_image = models.ImageField(storage=S3BotoStorage(location='img'), editable=False)
thumbnail_image = models.ImageField(storage=S3BotoStorage(location='img'), editable=False)
def __str__(self):
return self.title
def save(self):
super(Artwork, self).save()
image = Image.open(self.full_image_large, 'r')
(w, h) = image.size
for width, target in zip([900.0, 350.0, 120.0],
[self.full_image_large,
self.full_image,
self.thumbnail_image]):
r = width/w
im = image.resize((int(math.floor(r*w)),
int(math.floor(r*h))),
Image.ANTIALIAS)
im.save(target, format='JPEG')
So full_image_large
is editable and it is the one that the user is able to upload. I want this photo, regardless of its size to be resized (keeping the aspect ratio) to be 900px in width. Then I am trying to also resize the same photo to full_image
which should be 350px in width. Finally, I am trying to resize the same photo to thumbnail_image
which should be 120px in width.
所以full_image_large是可编辑的,它是用户能够上传的。我想要这张照片,不管它的大小是否要调整大小(保持宽高比)宽度为900px。然后我也尝试将相同的照片调整为full_image,宽度应为350px。最后,我试图将相同的照片调整为thumbnail_image,其宽度应为120px。
When I go to my site's admin url and save the object, I am getting the following error.
当我访问我的网站的管理员网址并保存对象时,我收到以下错误。
The 'full_image' attribute has no file associated with it.
The first image gets uploaded to Amazon S3 (if I comment out references to the two other images) just fine but nothing gets resized. If anyone can help me with the easiest way to accomplish what I am doing, that would be appreciated. Thanks. Note: I am using Python3.
第一个图像上传到Amazon S3(如果我注释掉对其他两个图像的引用)就好了,但没有任何内容可以调整大小。如果有人能用最简单的方法帮助我完成我正在做的事情,那将不胜感激。谢谢。注意:我使用的是Python3。
I have also tried using django-imagekit
without success.
我也尝试过使用django-imagekit但没有成功。
1 个解决方案
#1
1
Try using the following instead:
请尝试使用以下代码:
def save(self):
image = Image.open(self.full_image_large)
(w, h) = image.size
r900 = 900.0/w
im900 = image.resize((int(math.floor(r900*w)), int(math.floor(r900*h))), Image.ANTIALIAS)
im900.save(self.full_image_large)
r350 = 350.0/w
im350 = image.resize((int(math.floor(r350*w)), int(math.floor(r350*h))), Image.ANTIALIAS)
im350.save(self.full_image)
r120 = 120.0/w
im120 = image.resize((int(math.floor(r120*w)), int(math.floor(r120*h))), Image.ANTIALIAS)
im120.save(self.thumbnail_image)
super(Artwork, self).save()
You can do all three resize
operations on the same Image
instance - image
in this case. Just save the results of that operation in a new object for each size, then save that object instead of saving the original image
object.
您可以在同一个Image实例上执行所有三个调整大小操作 - 在这种情况下是图像。只需将该操作的结果保存在每个大小的新对象中,然后保存该对象而不是保存原始图像对象。
However, one of Python's main tenets is DRY - Don't Repeat Yourself. The above code can be refactored like so:
然而,Python的主要原则之一是DRY - 不要重复自己。上面的代码可以像这样重构:
def save(self):
image = Image.open(self.full_image_large)
(w, h) = image.size
for width, target in zip([900.0, 350.0, 120.0],
[self.full_image_large,
self.full_image,
self.thumbnail_image]):
r = width/w
im = image.resize((int(math.floor(r*w)),
int(math.floor(r*h))),
Image.ANTIALIAS)
im.save(target)
super(Artwork, self).save()
zip
creates a tuple of each width and target.
zip创建每个宽度和目标的元组。
#1
1
Try using the following instead:
请尝试使用以下代码:
def save(self):
image = Image.open(self.full_image_large)
(w, h) = image.size
r900 = 900.0/w
im900 = image.resize((int(math.floor(r900*w)), int(math.floor(r900*h))), Image.ANTIALIAS)
im900.save(self.full_image_large)
r350 = 350.0/w
im350 = image.resize((int(math.floor(r350*w)), int(math.floor(r350*h))), Image.ANTIALIAS)
im350.save(self.full_image)
r120 = 120.0/w
im120 = image.resize((int(math.floor(r120*w)), int(math.floor(r120*h))), Image.ANTIALIAS)
im120.save(self.thumbnail_image)
super(Artwork, self).save()
You can do all three resize
operations on the same Image
instance - image
in this case. Just save the results of that operation in a new object for each size, then save that object instead of saving the original image
object.
您可以在同一个Image实例上执行所有三个调整大小操作 - 在这种情况下是图像。只需将该操作的结果保存在每个大小的新对象中,然后保存该对象而不是保存原始图像对象。
However, one of Python's main tenets is DRY - Don't Repeat Yourself. The above code can be refactored like so:
然而,Python的主要原则之一是DRY - 不要重复自己。上面的代码可以像这样重构:
def save(self):
image = Image.open(self.full_image_large)
(w, h) = image.size
for width, target in zip([900.0, 350.0, 120.0],
[self.full_image_large,
self.full_image,
self.thumbnail_image]):
r = width/w
im = image.resize((int(math.floor(r*w)),
int(math.floor(r*h))),
Image.ANTIALIAS)
im.save(target)
super(Artwork, self).save()
zip
creates a tuple of each width and target.
zip创建每个宽度和目标的元组。