You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免每次保存Django模型对象时图片被重复缩放?

解决Django Book模型重复保存导致图片持续缩小的问题

问题根源

每次调用save()方法时,都会执行resize_image()对当前存储的图片重新压缩——而当前图片已经是上一次压缩后的版本,反复执行就会导致图片尺寸持续变小。

解决方案

只有在图片首次上传或图片被修改时,才执行图片压缩操作,避免重复处理。

修改代码

修改Book模型的save()方法,增加图片是否需要处理的判断逻辑:

class Book(models.Model):
    title = models.CharField(max_length=256)
    price = models.IntegerField()
    category = models.ForeignKey('Category', on_delete=models.PROTECT)
    rating = models.FloatField(validators=[MaxValueValidator(10), MinValueValidator(1)])
    discount = models.IntegerField(blank=True, default=0)
    final_price = models.IntegerField(blank=True)
    created_date = models.DateTimeField(auto_now_add=True)
    description = models.TextField(blank=True, null=True)
    count = models.IntegerField(default=0)
    author = models.ForeignKey('Author', on_delete=models.PROTECT)
    image = models.ImageField(upload_to=_get_product_cover_upload_path, null=True, blank=True)

    def resize_image(self):
        if not self.image:
            return  # 图片不存在时直接返回,避免报错
        img = Image.open(self.image.path)
        img.thumbnail((300, 300))
        img_w, img_h = img.size
        background = Image.new('RGBA', (400, 400), (255, 255, 255, 255))
        bg_w, bg_h = background.size
        offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2)
        background.paste(img, offset)
        background.save(self.image.path)

    def __str__(self):
        return f'{self.title}'

    def save(self, *args, **kwargs):
        # 修正final_price计算为整数运算,匹配IntegerField类型
        self.final_price = self.price * (100 - self.discount) // 100

        # 判断是否需要压缩图片
        need_resize = False
        if not self.pk:
            # 新建对象,图片为首次上传
            need_resize = True
        else:
            # 获取数据库中原始记录,对比图片是否修改
            original_book = Book.objects.get(pk=self.pk)
            if original_book.image != self.image:
                need_resize = True

        # 先执行父类的save操作
        super().save(*args, **kwargs)

        # 仅当需要且图片存在时,执行压缩
        if need_resize and self.image:
            self.resize_image()

额外优化说明

  1. 在resize_image()开头增加图片存在性判断,避免因图片字段为空导致的文件读取错误。
  2. 将final_price的计算改为整数除法//,确保结果为整数,匹配字段的IntegerField类型,避免浮点数截断问题。

内容的提问来源于stack exchange,提问作者sadegh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 21:45:17