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

在Summernote中删除文章时如何同步删除对应图片?

解决Django Admin删除Summernote文章时同步删除图片的最优方案

核心原因

Summernote的图片是嵌入在富文本字段的HTML标签中,而django-cleanup仅能识别模型中直接定义的FileField/ImageField,无法解析HTML内的图片路径,因此删除文章时不会自动清理这类图片。

方案实现步骤

1. 编写HTML图片路径提取工具函数

用BeautifulSoup解析富文本内容,提取所有<img>标签的本地文件路径:

from bs4 import BeautifulSoup
from django.conf import settings
import os

def extract_summernote_images(html_content):
    if not html_content:
        return []
    soup = BeautifulSoup(html_content, 'html.parser')
    img_tags = soup.find_all('img')
    image_paths = []
    for img in img_tags:
        src = img.get('src')
        if src and src.startswith(settings.MEDIA_URL):
            relative_path = src.replace(settings.MEDIA_URL, '')
            full_path = os.path.join(settings.MEDIA_ROOT, relative_path)
            image_paths.append(full_path)
    return image_paths

2. 利用Django信号处理文章删除后的图片清理

通过post_delete信号,在文章被删除后自动执行图片删除逻辑(假设你的文章模型为Article,富文本字段为content):

from django.db.models.signals import post_delete
from django.dispatch import receiver
from .models import Article
import os

@receiver(post_delete, sender=Article)
def delete_summernote_images_on_article_delete(sender, instance, **kwargs):
    image_paths = extract_summernote_images(instance.content)
    for path in image_paths:
        if os.path.exists(path):
            try:
                os.remove(path)
                # 若使用云存储(如S3),替换为以下代码:
                # from django.core.files.storage import default_storage
                # default_storage.delete(path.replace(settings.MEDIA_ROOT, ''))
            except Exception:
                # 可添加日志记录,避免删除失败中断流程
                pass

3. 可选:处理文章更新时的旧图片清理

如果更新文章时替换了图片,可通过pre_save信号对比新旧内容,删除未被保留的旧图片:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from .models import Article

@receiver(pre_save, sender=Article)
def delete_old_summernote_images_on_update(sender, instance, **kwargs):
    if instance.pk:
        old_instance = sender.objects.get(pk=instance.pk)
        old_images = extract_summernote_images(old_instance.content)
        new_images = extract_summernote_images(instance.content)
        images_to_delete = set(old_images) - set(new_images)
        for path in images_to_delete:
            if os.path.exists(path):
                try:
                    os.remove(path)
                except Exception:
                    pass

4. 确保信号生效

将信号代码放在models.py中,或在apps.py的ready()方法中导入信号模块:

# apps.py
from django.apps import AppConfig

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        import your_app_name.signals

注意事项

  • 需先安装依赖:pip install beautifulsoup4
  • 测试前建议备份媒体文件,避免误删
  • 可添加日志模块记录删除操作,方便排查异常

内容的提问来源于stack exchange,提问作者Jonasz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:08:17