From 7efcd28a8413b7a330f9c59c27b07e74aaac74c3 Mon Sep 17 00:00:00 2001 From: Johannes Hoppe Date: Tue, 6 Aug 2019 08:01:10 +0200 Subject: [PATCH] Fix #206 -- Overwrite variations by defaults We now overwrite files by default when a new files gets uploaded. This fixes an issue, where someone might upload a file with the same name twice the first initial variations get not replaced with a version of the newer file. It happens in the least IO consuming way. The rendervariations management command still behaves as before where variations are not replaced by default. --- stdimage/models.py | 21 +++++++++++---------- tests/test_commands.py | 10 +++++----- tests/test_models.py | 14 ++++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/stdimage/models.py b/stdimage/models.py index 1b54ffe..354dc09 100644 --- a/stdimage/models.py +++ b/stdimage/models.py @@ -48,24 +48,25 @@ def is_smaller(img, variation): return img.size[0] > variation['width'] \ or img.size[1] > variation['height'] - def render_variations(self, replace=False): + def render_variations(self, replace=True): """Render all image variations and saves them to the storage.""" for _, variation in self.field.variations.items(): self.render_variation(self.name, variation, replace, self.storage) @classmethod - def render_variation(cls, file_name, variation, replace=False, + def render_variation(cls, file_name, variation, replace=True, storage=default_storage): """Render an image variation and saves it to the storage.""" variation_name = cls.get_variation_name(file_name, variation['name']) - if storage.exists(variation_name): - if replace: - storage.delete(variation_name) - logger.info('File "%s" already exists and has been replaced.', - variation_name) - else: - logger.info('File "%s" already exists.', variation_name) - return variation_name + file_overwrite = getattr(storage, 'file_overwrite', False) + if not replace and storage.exists(variation_name): + logger.info('File "%s" already exists.', variation_name) + return variation_name + elif replace and not file_overwrite and storage.exists(variation_name): + logger.warning( + 'File "%s" already exists and will be overwritten.', variation_name + ) + storage.delete(variation_name) ImageFile.LOAD_TRUNCATED_IMAGES = True with storage.open(file_name) as f: diff --git a/tests/test_commands.py b/tests/test_commands.py index d772893..1e0b8b0 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -57,7 +57,7 @@ def test_no_replace(self, image_upload_file): file_path = obj.image.thumbnail.path assert os.path.exists(file_path) before = os.path.getmtime(file_path) - time.sleep(1) + time.sleep(0.1) call_command( 'rendervariations', 'tests.ThumbnailModel.image', @@ -71,7 +71,7 @@ def test_replace(self, image_upload_file): file_path = obj.image.thumbnail.path assert os.path.exists(file_path) before = os.path.getmtime(file_path) - time.sleep(1) + time.sleep(0.1) call_command( 'rendervariations', 'tests.ThumbnailModel.image', @@ -87,7 +87,7 @@ def test_ignore_missing(self, image_upload_file): assert os.path.exists(file_path) os.remove(file_path) assert not os.path.exists(file_path) - time.sleep(1) + time.sleep(0.1) call_command( 'rendervariations', 'tests.ThumbnailModel.image', @@ -101,7 +101,7 @@ def test_short_ignore_missing(self, image_upload_file): assert os.path.exists(file_path) os.remove(file_path) assert not os.path.exists(file_path) - time.sleep(1) + time.sleep(0.1) call_command( 'rendervariations', 'tests.ThumbnailModel.image', @@ -115,7 +115,7 @@ def test_no_ignore_missing(self, image_upload_file): assert os.path.exists(file_path) os.remove(file_path) assert not os.path.exists(file_path) - time.sleep(1) + time.sleep(0.1) with pytest.raises(CommandError): call_command( 'rendervariations', diff --git a/tests/test_models.py b/tests/test_models.py index a8b9006..021c912 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,5 +1,6 @@ import io import os +import time import pytest from django.conf import settings @@ -210,6 +211,19 @@ def test_render_variations_callback(self, db): file_path = obj.image.thumbnail.path assert os.path.exists(file_path) + def test_render_variations_overwrite(self, db, image_upload_file): + obj = ThumbnailModel.objects.create(image=image_upload_file) + file_path = obj.image.thumbnail.path + before = os.path.getmtime(file_path) + time.sleep(0.1) + os.remove(obj.image.path) + assert os.path.exists(file_path) + obj.image = image_upload_file + obj.save() + assert file_path == obj.image.thumbnail.path + after = os.path.getmtime(file_path) + assert before != after, obj.image.path + class TestValidators(TestStdImage): def test_max_size_validator(self, admin_client):