Django中使用PILLOW调整上传图片大小功能失效如何解决?
问题修复方案
问题根源
- 你在调用父类
save()方法之前就读取self.image.path:Django的ImageField只有执行完父类的保存逻辑后,才会把上传的文件写入到upload_to指定的images/目录下,提前读取路径会指向不存在的临时路径/错误路径,自然找不到文件。 - 原代码里调用父类
save时没有传递*args, **kwargs参数,会导致部分传入的保存参数失效,也可能引发文件存储异常。
修复方案
推荐直接读取ImageField的文件流来操作,不需要依赖本地路径,适配本地存储、云存储等所有存储场景,修正后的代码如下:
from django.db import models from django.template.defaultfilters import slugify from PIL import Image from io import BytesIO from django.core.files.base import ContentFile class Product(models.Model): name = models.CharField(max_length=250) description = models.TextField(max_length=2500) image = models.ImageField(upload_to="images/") price = models.IntegerField() slug = models.SlugField(blank=True, null=True) def save(self, *args, **kwargs): self.slug = slugify(f"{self.name}") # 先执行父类保存,确保文件已经被正确存储 super(Product, self).save(*args, **kwargs) # 打开图片文件流 img = Image.open(self.image.file) if img.height > 500 or img.width > 500: output_size = (500, 500) # 处理图片 img.thumbnail(output_size) # 保存处理后的图片到内存 img_byte_arr = BytesIO() # 保留原图片格式,也可以固定指定为JPEG等 img_format = img.format if img.format else 'JPEG' img.save(img_byte_arr, format=img_format) img_byte_arr.seek(0) # 覆盖原文件保存,save设为False避免重复触发save逻辑 self.image.save(self.image.name, ContentFile(img_byte_arr.read()), save=False) # 仅更新图片字段,避免循环调用save super(Product, self).save(update_fields=['image'])
补充说明
- 如果你确定只用本地文件存储,也可以简化写法:第一次父类save完成后直接操作
self.image.path读写即可,不需要走内存流的逻辑。 - 上述写法避免了循环调用save的问题,第二次调用父类save仅更新图片字段,不会重复执行整个保存逻辑。
内容的提问来源于stack exchange,提问作者mateuszlaczynski
相关产品推荐
相关产品推荐

