# Imports
# from django.conf import settings
from django.db.models import FileField
import os
# Exports
__all__ = (
"handle_file_removal_on_change",
"handle_file_removal_on_delete",
)
# Receivers
[docs]def handle_file_removal_on_change(sender, **kwargs):
"""Remove the files associated with a model when they have changed on the instance.
.. code-block:: python
from django.db.models.signals import pre_save
from superdjango.storage.receivers import handle_file_removal_on_change
from myapp.models import Document
pre_save.connect(
handle_file_removal_on_change,
Document,
dispatch_uid="myapp_document_handle_file_removal_on_change"
)
"""
instance = kwargs['instance']
if not instance.pk:
return False
old_instance = sender.objects.get(pk=instance.pk)
# noinspection PyProtectedMember
for field in instance._meta.get_fields():
if isinstance(field, FileField):
old_field = getattr(old_instance, field.name)
new_field = getattr(instance, field.name)
if old_field.file != new_field.file:
path = str(old_field.file)
if os.path.isfile(path):
os.remove(path)
[docs]def handle_file_removal_on_delete(sender, **kwargs):
"""Remove any files associated with a model when an instance is deleted.
.. code-block:: python
from django.db.models.signals import post_delete
from superdjango.storage.receivers import handle_file_removal_on_delete
from myapp.models import Document
post_delete.connect(
handle_file_removal_on_delete,
Document,
dispatch_uid="myapp_document_handle_file_removal_on_delete"
)
"""
# A management command (which would require specifying the models for which file uploads are included) or a signal
# handler appears to be the only way to deal with files orphaned by a model delete.
# https://stackoverflow.com/a/16041527/241720
instance = kwargs['instance']
# noinspection PyProtectedMember
for field in instance._meta.get_fields():
if isinstance(field, FileField):
_field = getattr(instance, field.name)
path = str(_field.file)
if path and os.path.isfile(path):
os.remove(path)