Python Django如何为Article模型ImageField生成同目录下的_thumb后缀缩略图
实现方案
首先确保已安装图片处理依赖Pillow:
pip install pillow
方法一:重写模型save方法(最简单直接)
直接修改Article模型的save方法,在原图片保存完成后自动生成缩略图,代码如下:
import os from PIL import Image from django.db import models from django.urls import reverse class Article(models.Model): title = models.CharField(max_length=200, verbose_name='Name',) photo = models.ImageField(upload_to='news/%Y/%m/%d/', blank=True, verbose_name='Image') def __str__(self): return self.title def get_absolute_url(self): return reverse('article', kwargs={'art_id': self.id}) def save(self, *args, **kwargs): # 先执行原保存逻辑,确保原图片已上传存储 super().save(*args, **kwargs) # 只有当photo字段有内容时才处理缩略图 if self.photo: # 解析原图片的路径和文件名 img_path = self.photo.path img_dir = os.path.dirname(img_path) img_fullname = os.path.basename(img_path) img_name, _ = os.path.splitext(img_fullname) # 生成缩略图的存储路径 thumb_path = os.path.join(img_dir, f"{img_name}_thumb.jpg") # 打开原图片并处理 with Image.open(img_path) as img: # 可自定义缩略图最大尺寸,示例为宽高最大300px max_size = (300, 300) # 保持原图比例缩放 img.thumbnail(max_size) # 处理RGBA、P格式转JPG的透明通道兼容问题 if img.mode in ("RGBA", "P"): img = img.convert("RGB") # 保存为JPG格式,质量可在0-100区间自定义 img.save(thumb_path, "JPEG", quality=85)
方法二:使用Django信号(适合多模型复用场景)
如果多个模型都需要生成缩略图,可以用post_save信号实现逻辑解耦:
- 首先在应用目录下新建
signals.py,写入以下代码:
import os from PIL import Image from django.db.models.signals import post_save from django.dispatch import receiver from .models import Article @receiver(post_save, sender=Article) def generate_thumbnail(sender, instance, created, **kwargs): if not instance.photo: return # 路径解析、图片处理逻辑和save方法中的实现完全一致 img_path = instance.photo.path img_dir = os.path.dirname(img_path) img_fullname = os.path.basename(img_path) img_name, _ = os.path.splitext(img_fullname) thumb_path = os.path.join(img_dir, f"{img_name}_thumb.jpg") with Image.open(img_path) as img: max_size = (300, 300) img.thumbnail(max_size) if img.mode in ("RGBA", "P"): img = img.convert("RGB") img.save(thumb_path, "JPEG", quality=85)
- 再到应用的
apps.py中注册信号:
from django.apps import AppConfig class YourAppConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = '替换为你的应用名称' def ready(self): import 替换为你的应用名称.signals
注意事项
- 可根据业务需求调整
max_size参数自定义缩略图尺寸,调整quality参数平衡缩略图清晰度和文件大小 - 如果需要删除文章时同步删除对应缩略图,可新增
pre_delete信号,逻辑和生成逻辑类似,找到对应路径删除文件即可 - 如果使用第三方云存储(如OSS、S3),需要将本地路径读写逻辑替换为对应存储服务的文件操作接口
内容的提问来源于stack exchange,提问作者AeroFlow
相关产品推荐
相关产品推荐

