在 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)

希望对其他人有所帮助。

Link: https://github.com/un1t/django-resized

您可以创建一个 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 元组中提供图像字段名称。