Django Summernote: How to delete attachment files from server when removing them from admin?
When I delete a file from the Attachment model (which is provided by django-summernote), the record is removed from the database, but the actual file remains on the server.
I want to make sure that whenever an attachment is deleted, its file is also removed from the filesystem.
You can achieve this by overriding the delete method of the Attachment model. Since Attachment is part of Django Summernote, you can create a proxy model and override its delete method to remove the file from the server before deleting the database record.
models.py
from django.contrib import admin
from django_summernote.models import Attachment
# Create a proxy model
class CustomeAttachment(Attachment):
class Meta:
proxy = True
# You can add verbose names here
def delete(self, *args, **kwargs):
if self.file and os.path.isfile(self.file.path):
os.remove(self.file.path)
super().delete(*args, **kwargs)
admin.py
from django_summernote.models import Attachment
from .models import CustomeAttachment
from django_summernote.admin import AttachmentAdmin
# Unregister the original Attachment model from admin
admin.site.unregister(Attachment)
# Register the proxy model with admin
admin.site.register(CustomeAttachment, AttachmentAdmin)
We create a proxy model
AttachmentFathat inherits fromAttachment.The
deletemethod is overridden to remove the actual file from the filesystem before callingsuper().delete()to remove the database record.Finally, we unregister the original
Attachmentmodel from the admin and register our proxy model so that the delete behavior is applied in the admin panel.
This approach ensures that whenever an attachment is deleted from Django admin, its file is also removed from the server.
For deleting files from the filesystem I would suggest using a post_delete signal.
import shutil
from pathlib import Path
from django.db.models.signals import post_delete
from django.dispatch import receiver
from django_summernote.models import Attachment
@receiver(post_delete, sender=Attachment)
def delete_attachment_file(sender, instance, **kwargs):
if not instance.file or not Path(instance.file).exists():
return
if Path(instance.file).is_file():
Path(instance.file).unlink()
else:
# NOTE: if it's a dir this will remove the dir and everything in it
# so you might not want to review and adjust that
shutil.rmtree(instance.file)
You can read the official Django documentation to learn more about signals adn how to set them up: https://docs.djangoproject.com/en/5.2/topics/signals/ (keep in mind this is the docs for django 5.2)