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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 17:06:05