如何避免每次保存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()
额外优化说明
- 在
resize_image()开头增加图片存在性判断,避免因图片字段为空导致的文件读取错误。 - 将
final_price的计算改为整数除法//,确保结果为整数,匹配字段的IntegerField类型,避免浮点数截断问题。
内容的提问来源于stack exchange,提问作者sadegh
相关产品推荐
相关产品推荐

