93 lines
3.1 KiB
Python
93 lines
3.1 KiB
Python
from django.core.files.storage import FileSystemStorage
|
|
import os
|
|
from django.db.models.signals import post_save, post_delete, pre_save
|
|
from django.db.models.fields.files import FileField
|
|
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
|
|
|
from django.conf import settings as django_settings
|
|
from image.storage import IMAGE_CACHE_STORAGE
|
|
|
|
|
|
def safe_delete(path):
|
|
if isinstance(IMAGE_CACHE_STORAGE, FileSystemStorage):
|
|
full_path = os.path.join(IMAGE_CACHE_STORAGE.location, path)
|
|
if os.path.isdir(full_path):
|
|
os.rmdir(full_path)
|
|
return
|
|
IMAGE_CACHE_STORAGE.delete(path)
|
|
|
|
|
|
def remove_directory(dir_path):
|
|
try:
|
|
# Since no all storages support exists for directories, we check for OSError
|
|
contents = IMAGE_CACHE_STORAGE.listdir(dir_path)
|
|
except OSError:
|
|
pass
|
|
else:
|
|
for directory in contents[0]:
|
|
safe_delete(os.path.join(dir_path, directory))
|
|
for filename in contents[1]:
|
|
safe_delete(os.path.join(dir_path, filename))
|
|
|
|
if IMAGE_CACHE_STORAGE.exists(dir_path):
|
|
# In some storages like amazon S3 there are no directories
|
|
safe_delete(dir_path)
|
|
|
|
|
|
def remove_cache(image_path):
|
|
if image_path:
|
|
remove_directory(image_path)
|
|
|
|
|
|
def prepare_image_cache_cleanup(sender, instance=None, **kwargs):
|
|
if instance is None:
|
|
return
|
|
instance.old_image_fields = {}
|
|
|
|
old_instance = None
|
|
|
|
for field in instance._meta.fields:
|
|
if isinstance(field, FileField):
|
|
if not old_instance:
|
|
try:
|
|
old_instance = sender.objects.get(pk=instance.pk)
|
|
except (ObjectDoesNotExist, MultipleObjectsReturned):
|
|
return
|
|
|
|
instance.old_image_fields[field.attname] = field.value_to_string(old_instance)
|
|
|
|
|
|
def clear_prepared_image_cache_cleanup(sender, instance=None, created=False, **kwargs):
|
|
if created:
|
|
return
|
|
if instance is None:
|
|
return
|
|
for field in instance._meta.fields:
|
|
if isinstance(field, FileField):
|
|
if instance.old_image_fields[field.attname] != field.value_to_string(instance):
|
|
remove_cache(instance.old_image_fields[field.attname])
|
|
|
|
|
|
def clear_image_cache(sender, instance, **kwargs):
|
|
for field in instance._meta.fields:
|
|
if isinstance(field, FileField):
|
|
remove_cache(field.value_to_string(instance))
|
|
|
|
|
|
pre_save.connect(prepare_image_cache_cleanup)
|
|
post_save.connect(clear_prepared_image_cache_cleanup)
|
|
post_delete.connect(clear_image_cache)
|
|
|
|
#reversion compatibility
|
|
if 'reversion' in django_settings.INSTALLED_APPS:
|
|
try:
|
|
from reversion.models import pre_revision_commit, post_revision_commit
|
|
|
|
pre_revision_commit.connect(prepare_image_cache_cleanup)
|
|
post_revision_commit.connect(clear_prepared_image_cache_cleanup)
|
|
except ImportError:
|
|
pass
|
|
|
|
# http://bakery-app01-static.s3.amazonaws.com/image/actuality/file0001116000079.jpg/image_token_73ff82d8ce1577a8a22f5a7d29a772a3ffc6e76c
|
|
|
|
remove_directory('actuality/file0001116000079.jpg') |