在 Django 中调整和更新图像
Resizing and updating image in Django
我正在重写我的保存方法,因为我想调整图像的大小。我的问题在这段代码中很明显,保存数据后发生的事情是 django 开始无限循环。当然是因为我正在检查 self.vertical 是否已设置(并且始终已设置)。始终调用保存方法。
我可以通过检查我的 self.id 是否为 none 来解决这个问题,但是代码将仅适用于新条目,如果用户尝试更新,则不会发生任何变化,因为 id 不为空。
我还尝试向 kwargs 弹出一个错误的参数,并在保存后设置为 true,但也没有用。有人知道我该如何解决这个问题?
PS:get_thumbnail是sorl缩略图插件的方法
def save(self, *args, **kwargs):
if self.vertical_poster:
super(Movie, self).save(*args, **kwargs)
resized_vertical = get_thumbnail(self.vertical_poster, "155x240", quality=99)
#save the new resized file
self.vertical_poster.save(resized_vertical.name, ContentFile(resized_vertical.read()), True)
super(Movie, self).save(*args, **kwargs)
任何想法或示例代码将不胜感激!谢谢
您可以检查图像是否已经达到您想要的尺寸。我想你可以使用 https://pypi.python.org/pypi/dimensions 来简化
def save(self, *args, **kwargs):
if self.vertical_poster:
import dimensions
# Set desired dimensions
width = 155
height = 240
image_info = dimensions.dimensions(self.vertical_poster)
if image_info[0] != width and image_info[1] != height:
dimension = '%dx%d' % (width, height)
resized_vertical = get_thumbnail(self.vertical_poster, dimension, quality=99)
#save the new resized file
self.vertical_poster.save(resized_vertical.name, ContentFile(resized_vertical.read()), True)
super(Movie, self).save(*args, **kwargs)
希望对您有所帮助。
如果你使用 ImageField,你可以这样做:
def save(self, *args, **kwargs):
if self.vertical_poster.x != 155 or self.vertical_poster.y != 240:
resized_vertical = get_thumbnail(self.vertical_poster, "155x240", quality=99)
# save the new resized file
self.vertical_poster.save(resized_vertical.name, ContentFile(resized_vertical.read()), True)
super(Movie, self).save(*args, **kwargs)
我的解决方案没有覆盖我的保存方法。我做了一些不同的事情:
我决定使用 "django-resized"。此插件兼容 "sorl-thumbnail" 并在模型字段上将图像原点调整为指定大小,如下所示:
from django_resized import ResizedImageField
class Movie(models.Model):
....
vertical_poster = ResizedImageField(upload_to="movies", width=155, height=240)
希望对其他人有所帮助。
您可以创建一个 mixin 并在任何您想要的地方使用。
mixins.py
from io import BytesIO
from PIL import Image
class ShrinkImageMixin:
def shrink_image(self, field_name, resize_shape):
img: Image = Image.open(getattr(self, field_name))
img.thumbnail(self.get_shrinked_size(field_name, resize_shape), Image.ANTIALIAS)
image_file = BytesIO()
img.save(image_file, 'jpg')
getattr(self, field_name).file = image_file
def get_shrinked_size(self, field_name, resize_shape):
actual_img_width, actual_img_height = getattr(self, field_name).width, getattr(self, field_name).height
ratio = min(resize_shape[0] / actual_img_width, resize_shape[1] / actual_img_height)
return int(actual_img_width * ratio), int(actual_img_height * ratio)
models.py
from .mixins import ShrinkImageMixin
class Article(ShrinkImageMixin, models.Model):
...
background_image = models.ImageField()
...
def save(self, *args, **kwargs):
self.shrink_image('background_image', (750, 375))
super(Article, self).save()
这会将您的图片缩小到您想要的尺寸,同时保持宽高比。您只需要在模型和 resize_shpe 元组中提供图像字段名称。
我正在重写我的保存方法,因为我想调整图像的大小。我的问题在这段代码中很明显,保存数据后发生的事情是 django 开始无限循环。当然是因为我正在检查 self.vertical 是否已设置(并且始终已设置)。始终调用保存方法。
我可以通过检查我的 self.id 是否为 none 来解决这个问题,但是代码将仅适用于新条目,如果用户尝试更新,则不会发生任何变化,因为 id 不为空。
我还尝试向 kwargs 弹出一个错误的参数,并在保存后设置为 true,但也没有用。有人知道我该如何解决这个问题?
PS:get_thumbnail是sorl缩略图插件的方法
def save(self, *args, **kwargs):
if self.vertical_poster:
super(Movie, self).save(*args, **kwargs)
resized_vertical = get_thumbnail(self.vertical_poster, "155x240", quality=99)
#save the new resized file
self.vertical_poster.save(resized_vertical.name, ContentFile(resized_vertical.read()), True)
super(Movie, self).save(*args, **kwargs)
任何想法或示例代码将不胜感激!谢谢
您可以检查图像是否已经达到您想要的尺寸。我想你可以使用 https://pypi.python.org/pypi/dimensions 来简化
def save(self, *args, **kwargs):
if self.vertical_poster:
import dimensions
# Set desired dimensions
width = 155
height = 240
image_info = dimensions.dimensions(self.vertical_poster)
if image_info[0] != width and image_info[1] != height:
dimension = '%dx%d' % (width, height)
resized_vertical = get_thumbnail(self.vertical_poster, dimension, quality=99)
#save the new resized file
self.vertical_poster.save(resized_vertical.name, ContentFile(resized_vertical.read()), True)
super(Movie, self).save(*args, **kwargs)
希望对您有所帮助。
如果你使用 ImageField,你可以这样做:
def save(self, *args, **kwargs):
if self.vertical_poster.x != 155 or self.vertical_poster.y != 240:
resized_vertical = get_thumbnail(self.vertical_poster, "155x240", quality=99)
# save the new resized file
self.vertical_poster.save(resized_vertical.name, ContentFile(resized_vertical.read()), True)
super(Movie, self).save(*args, **kwargs)
我的解决方案没有覆盖我的保存方法。我做了一些不同的事情:
我决定使用 "django-resized"。此插件兼容 "sorl-thumbnail" 并在模型字段上将图像原点调整为指定大小,如下所示:
from django_resized import ResizedImageField
class Movie(models.Model):
....
vertical_poster = ResizedImageField(upload_to="movies", width=155, height=240)
希望对其他人有所帮助。
您可以创建一个 mixin 并在任何您想要的地方使用。
mixins.py
from io import BytesIO
from PIL import Image
class ShrinkImageMixin:
def shrink_image(self, field_name, resize_shape):
img: Image = Image.open(getattr(self, field_name))
img.thumbnail(self.get_shrinked_size(field_name, resize_shape), Image.ANTIALIAS)
image_file = BytesIO()
img.save(image_file, 'jpg')
getattr(self, field_name).file = image_file
def get_shrinked_size(self, field_name, resize_shape):
actual_img_width, actual_img_height = getattr(self, field_name).width, getattr(self, field_name).height
ratio = min(resize_shape[0] / actual_img_width, resize_shape[1] / actual_img_height)
return int(actual_img_width * ratio), int(actual_img_height * ratio)
models.py
from .mixins import ShrinkImageMixin
class Article(ShrinkImageMixin, models.Model):
...
background_image = models.ImageField()
...
def save(self, *args, **kwargs):
self.shrink_image('background_image', (750, 375))
super(Article, self).save()
这会将您的图片缩小到您想要的尺寸,同时保持宽高比。您只需要在模型和 resize_shpe 元组中提供图像字段名称。