1
0
mirror of https://github.com/taigaio/taiga-back synced 2025-10-06 00:02:52 +02:00
Files
taiga-back/taiga/base/signals/cleanup_files.py
David Barragán Merino e7fad0b5cc chore: migrate to django 3.2
2023-02-24 13:05:37 +01:00

83 lines
2.3 KiB
Python

# -*- coding: utf-8 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Copyright (c) 2021-present Kaleidos Ventures SL
from django.apps import apps
from django.db import models, connection
from django.db.models.signals import pre_save, post_delete
from django.dispatch import Signal
import logging
logger = logging.getLogger(__name__)
cleanup_pre_delete = Signal()
cleanup_post_delete = Signal()
def _find_models_with_filefield():
result = []
for model in apps.get_models():
for field in model._meta.fields:
if isinstance(field, models.FileField):
result.append(model)
break
return result
def _delete_file(file_obj):
def delete_from_storage():
try:
cleanup_pre_delete.send(sender=None, file=file_obj)
storage.delete(file_obj.name)
cleanup_post_delete.send(sender=None, file=file_obj)
except Exception:
logger.exception("Unexpected exception while attempting "
"to delete old file '%s'".format(file_obj.name))
storage = file_obj.storage
if storage and storage.exists(file_obj.name):
connection.on_commit(delete_from_storage)
def _get_file_fields(instance):
return filter(
lambda field: isinstance(field, models.FileField),
instance._meta.fields,
)
def remove_files_on_change(sender, instance, **kwargs):
if not instance.pk:
return
try:
old_instance = sender.objects.get(pk=instance.pk)
except instance.DoesNotExist:
return
for field in _get_file_fields(instance):
old_file = getattr(old_instance, field.name)
new_file = getattr(instance, field.name)
if old_file and old_file != new_file:
_delete_file(old_file)
def remove_files_on_delete(sender, instance, **kwargs):
for field in _get_file_fields(instance):
file_to_delete = getattr(instance, field.name)
if file_to_delete:
_delete_file(file_to_delete)
def connect_cleanup_files_signals():
for model in _find_models_with_filefield():
pre_save.connect(remove_files_on_change, sender=model)
post_delete.connect(remove_files_on_delete, sender=model)