Skip to content

First stab at deleting file on update #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions thumbnails/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def __init__(self, *args, **kwargs):
if kwargs.get('storage'):
raise ValueError('Please define storage backend in settings.py instead on the field itself')
kwargs['storage'] = storage.get_backend()
self.delete_on_update = kwargs.pop('delete_on_update', False)
self.metadata_backend = metadata.get_backend()
super(ImageField, self).__init__(*args, **kwargs)

Expand All @@ -28,7 +29,18 @@ def pre_save(self, model_instance, add):
"""
file = getattr(model_instance, self.attname)

# new file is assigned
if file and not file._committed:
# detect if there are old file needs to be cleaned
old_file = getattr(type(model_instance).objects.get(id=model_instance.id),
self.attname)

if old_file:
all_thumbs = [thumb for thumb in old_file.thumbnails.all()]
for thumb_size in all_thumbs:
old_file.thumbnails.delete(thumb_size)
old_file.delete()

image_file = file
if self.resize_source_to:
file.seek(0)
Expand Down
3 changes: 3 additions & 0 deletions thumbnails/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ def save(self, name, content, save=True):
self.metadata_backend.add_source(self.name)
return thumbnail

def delete(self, save=True):
super(ThumbnailedImageFile, self).delete(save)


class ThumbnailManager(object):
"""A class that manages creation and retrieval of thumbnails."""
Expand Down
2 changes: 1 addition & 1 deletion thumbnails/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@


class TestModel(models.Model):
avatar = ImageField(upload_to='avatars', resize_source_to='source')
avatar = ImageField(upload_to='avatars', resize_source_to='source', delete_on_update=True)
profile_picture = ImageField(upload_to='avatars', blank=True, null=True, resize_source_to='source')
36 changes: 31 additions & 5 deletions thumbnails/tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ def setUp(self):
with open('thumbnails/tests/tests.png', 'rb') as image_file:
self.instance.avatar = File(image_file)
self.instance.save()

self.avatar_folder = \
os.path.join(self.instance.avatar.storage.temporary_location, 'avatars')
self.avatar_thumb_folder = \
os.path.join(self.instance.avatar.storage.temporary_location, conf.BASE_DIR, 'avatars')
self.basename = os.path.basename(self.instance.avatar.path)
self.filename, self.ext = os.path.splitext(self.basename)
Expand All @@ -29,19 +32,19 @@ def tearDown(self):
def test_image_field(self):

# 1. Test for thumbnail creation
self.assertFalse(os.path.isfile(os.path.join(self.avatar_folder, self.filename + '_small' + self.ext)))
self.assertFalse(os.path.isfile(os.path.join(self.avatar_thumb_folder, self.filename + '_small' + self.ext)))
thumb = self.instance.avatar.thumbnails.create(size='small')
self.assertTrue(os.path.isfile(os.path.join(self.avatar_folder, self.filename + '_small' + self.ext)))
self.assertTrue(os.path.isfile(os.path.join(self.avatar_thumb_folder, self.filename + '_small' + self.ext)))

# Make sure the returned thumbnail is of thumbnail class, not metadata
self.assertTrue(isinstance(thumb, Thumbnail))
# 2. Test for getting thumbnail
self.assertEqual(thumb, self.instance.avatar.thumbnails.get(size='small'))

# 3. Test for thumbnail deletion
self.assertTrue(os.path.isfile(os.path.join(self.avatar_folder, self.filename + '_small' + self.ext)))
self.assertTrue(os.path.isfile(os.path.join(self.avatar_thumb_folder, self.filename + '_small' + self.ext)))
self.instance.avatar.thumbnails.delete(size='small')
self.assertFalse(os.path.isfile(os.path.join(self.avatar_folder, self.filename + '_small' + self.ext)))
self.assertFalse(os.path.isfile(os.path.join(self.avatar_thumb_folder, self.filename + '_small' + self.ext)))

def test_thumbnail_field(self):
# Make sure ThumbnailManager return the correct thumbnail
Expand All @@ -58,7 +61,7 @@ def test_thumbnail_field(self):

# Test for name clashing with another file with the same name
self.instance.avatar.thumbnails.delete('large')
open(os.path.join(self.avatar_folder, 'tests_large.png'), 'w').close()
open(os.path.join(self.avatar_thumb_folder, 'tests_large.png'), 'w').close()
self.instance.avatar.thumbnails.create('large')

# Due to uuid4 for file name, this should not clash
Expand Down Expand Up @@ -142,3 +145,26 @@ def test_resize_source_to_none(self):
with open('thumbnails/tests/tests.png', 'rb') as image_file:
self.instance.profile_picture = File(image_file)
self.instance.save()

def test_delete_on_update(self):
# create thumbnails + sanity check for file existence
self.instance.avatar.thumbnails.large
self.instance.avatar.thumbnails.small

original_file = os.path.join(self.avatar_folder, self.filename + self.ext)
small_thumb = os.path.join(self.avatar_thumb_folder, self.filename + '_small' + self.ext)
large_thumb = os.path.join(self.avatar_thumb_folder, self.filename + '_large' + self.ext)

self.assertTrue(os.path.isfile(original_file))
self.assertTrue(os.path.isfile(small_thumb))
self.assertTrue(os.path.isfile(large_thumb))

# if file is updated
with open('thumbnails/tests/tests.png', 'rb') as image_file:
self.instance.avatar = File(image_file)
self.instance.save()

# make sure all old files are deleted
self.assertFalse(os.path.isfile(original_file))
self.assertFalse(os.path.isfile(small_thumb))
self.assertFalse(os.path.isfile(large_thumb))