如何在Django中用PILLOW压缩上传图片?求完整使用文档
Django views.py 中使用 Pillow 实现图片压缩的完整方案
Hey there! I’ve been stuck on this exact issue before — getting Pillow to work smoothly with Django for image compression can feel frustrating when tutorials skip over the little details. Let’s put together a complete, tested implementation that you can use right away.
第一步:确保 Pillow 已安装
首先确认你的环境里装了 Pillow,如果没装,运行:
pip install pillow
第二步:编写可复用的图片压缩函数
先写一个通用的压缩函数,它能处理不同格式的图片(JPEG/PNG),支持尺寸调整和质量控制,放在你的views.py或者单独的utils文件里都可以:
from PIL import Image import os from django.conf import settings def compress_image(image_path, output_path=None, quality=60, max_size=(1920, 1080)): """ 压缩图片并保存 :param image_path: 原始图片的路径 :param output_path: 压缩后图片的保存路径(默认覆盖原文件) :param quality: 压缩质量(1-100,JPEG有效;PNG建议用默认) :param max_size: 图片最大尺寸(宽, 高),超过则按比例缩放 """ if not output_path: output_path = image_path try: # 打开图片 with Image.open(image_path) as img: # 处理透明度(PNG转RGB避免保存JPEG时出错) if img.mode in ("RGBA", "P"): img = img.convert("RGB") # 按比例缩放图片到指定最大尺寸 img.thumbnail(max_size, Image.Resampling.LANCZOS) # 根据图片格式设置压缩参数 file_ext = os.path.splitext(image_path)[1].lower() save_args = {} if file_ext in (".jpg", ".jpeg"): save_args["quality"] = quality save_args["optimize"] = True elif file_ext == ".png": save_args["optimize"] = True # PNG用optimize参数优化 # 保存压缩后的图片 img.save(output_path, **save_args) return True except Exception as e: print(f"压缩图片出错: {str(e)}") return False
第三步:在 Django View 中使用这个函数
下面是几个常见场景的示例:
场景1:处理用户上传的图片(表单提交)
假设你有一个接收图片上传的View,在保存到模型之前先压缩:
from django.shortcuts import render, redirect from .forms import ImageUploadForm from .models import UploadedImage def upload_and_compress(request): if request.method == "POST": form = ImageUploadForm(request.POST, request.FILES) if form.is_valid(): # 先保存上传的图片到临时位置(Django默认会存在内存或临时文件) uploaded_image = form.cleaned_data["image"] # 获取图片的完整路径 temp_path = os.path.join(settings.MEDIA_ROOT, uploaded_image.name) # 先把上传的文件写到磁盘(因为Pillow需要文件路径) with open(temp_path, "wb+") as f: for chunk in uploaded_image.chunks(): f.write(chunk) # 压缩图片(这里直接覆盖原文件,也可以指定新路径) compress_image(temp_path, quality=50) # 把压缩后的图片保存到模型 instance = UploadedImage(image=uploaded_image) instance.save() # 删除临时文件(如果不需要的话) os.remove(temp_path) return redirect("success_page") else: form = ImageUploadForm() return render(request, "upload.html", {"form": form})
场景2:压缩模型中已存在的图片
如果你的模型里已经有图片,想要批量或单个压缩:
from .models import Product def compress_product_images(request): # 获取所有带图片的Product对象 products = Product.objects.filter(image__isnull=False) for product in products: # 获取图片的本地路径 image_path = product.image.path # 压缩图片,覆盖原文件 compress_image(image_path, quality=65) return render(request, "compress_done.html")
常见问题排查(为什么你之前可能失败了?)
- 格式不兼容:比如直接把PNG图片存为JPEG而没有转成RGB模式,会报错
- 路径错误:没有正确获取Django的
MEDIA_ROOT,导致Pillow找不到文件 - 权限问题:服务器没有写入目标路径的权限,检查文件夹的读写权限
- 参数错误:给PNG图片设置
quality参数(PNG的质量参数和JPEG不同,建议用optimize=True)
内容的提问来源于stack exchange,提问作者Emizy
相关产品推荐
相关产品推荐

