Skip to content
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

Deletion thumbnail sorl #120

Merged
merged 9 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from 8 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
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ CHANGELOG
1.0.26+dev (XXXX-XX-XX)
---------------------------

* Remove file when property has been removed or value become empty
* Remove file when property has been removed or value become empty
* Fix thumbnail regeneration with same name of main picture

1.0.26 (2022-05-05)
---------------------------
Expand Down
3 changes: 1 addition & 2 deletions terra_geocrud/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,7 @@ def thumbnail(self):

def delete(self, *args, **kwargs):
""" Delete image and thumbnail at deletion """
self.image.storage.delete(self.image.name)
delete(self.image)
delete(self.image, delete_file=True)
super().delete(*args, **kwargs)

class Meta:
Expand Down
8 changes: 3 additions & 5 deletions terra_geocrud/properties/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ def generate_storage_file_path(prop, value, feature):


def delete_old_picture_property(file_prop, old_properties):
storage = get_storage()
old_value = old_properties.get(file_prop)
old_storage_file_path = old_value.split(';name=')[-1].split(';')[0] if old_value else None
if old_storage_file_path:
storage.delete(old_storage_file_path)
submarcos marked this conversation as resolved.
Show resolved Hide resolved
delete(old_storage_file_path)
delete(old_storage_file_path, delete_file=True)
submarcos marked this conversation as resolved.
Show resolved Hide resolved


def get_files_properties(feature):
Expand Down Expand Up @@ -83,10 +81,10 @@ def store_feature_files(feature, old_properties=None):
# check if file has been saved in storage
if file_content != fake_content:
delete_old_picture_property(file_prop, old_properties)
storage.save(storage_file_path, ContentFile(base64.b64decode(file_content)))
stored_name = storage.save(storage_file_path, ContentFile(base64.b64decode(file_content)))
# patch file_infos with new path
detail_infos = file_info.split(';name=')
new_info = f"{detail_infos[0]};name={storage_file_path}"
new_info = f"{detail_infos[0]};name={stored_name}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because it's not only name but path in storage I prefer to keep storage_file_path

feature.properties[file_prop] = f'{new_info};base64,{fake_content}'
feature.save()
else:
Expand Down
27 changes: 27 additions & 0 deletions terra_geocrud/tests/test_properties/test_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,30 @@ def test_remove_crudviewproperty_remove_attached_files(self):
sync_layer_schema(self.crud_view)
self.assertFalse(storage.exists(old_thumbnail.name))
self.assertFalse(storage.exists(old_storage_file_path))

def test_same_name_file_crudviewproperty(self):
store_feature_files(self.feature_with_file_name, self.feature_with_file_name.properties)
storage = get_storage()
old_property_value = self.feature_with_file_name.properties.get(self.property_key)
old_storage_file_path = old_property_value.split(';name=')[-1].split(';')[0]
old_thumbnail = thumbnail_backend.get_thumbnail(old_storage_file_path, "500x500", crop='noop', upscale=False)
self.assertTrue(storage.exists(old_thumbnail.name))
self.assertTrue(storage.exists(old_storage_file_path))
storage.delete(old_storage_file_path)

base_64_img = 'data:image/png;name=toto.png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAFUlEQVR42mP8z8BQz0AEYBxVSF+FABJADveWkH6oAAAAAElFTkSuQmCC '

self.feature_with_file_name.properties[self.property_key] = base_64_img

self.feature_with_file_name.save()
store_feature_files(self.feature_with_file_name, self.feature_with_file_name.properties)

new_property_value = self.feature_with_file_name.properties.get(self.property_key)
new_storage_file_path = new_property_value.split(';name=')[-1].split(';')[0]

sync_layer_schema(self.crud_view)

new_thumbnail = thumbnail_backend.get_thumbnail(new_storage_file_path, "500x500", crop='noop', upscale=False)

self.assertEqual(old_storage_file_path, new_storage_file_path)
self.assertNotEqual(old_thumbnail.url, new_thumbnail.url)
41 changes: 41 additions & 0 deletions terra_geocrud/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,24 @@ def setUp(self):
self.extra_layer = LayerExtraGeom.objects.create(geom_type=GeometryTypes.MultiPolygon,
title='extra geom 1',
layer=self.view_1.layer)
self.relation_layer = LayerFactory.create()
self.relation_crud_view = factories.CrudViewFactory()
# relation with view
LayerRelation.objects.create(
name="relation_1",
relation_type='distance',
origin=self.view_1.layer,
destination=self.relation_crud_view.layer,
settings={"distance": 100}
)
# relation without view
LayerRelation.objects.create(
name="relation_2",
relation_type='distance',
origin=self.view_1.layer,
destination=self.relation_layer,
settings={"distance": 100}
)

def test_list_endpoint(self):
response = self.client.get(reverse('crudview-list'))
Expand Down Expand Up @@ -169,6 +187,29 @@ def test_grouped_ui_schema(self):
group_1.delete()
group_2.delete()

def test_map_layers(self):
response = self.client.get(reverse('crudview-detail', args=(self.view_1.pk,)))
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = response.json()

self.assertDictEqual(data['map_layers'][0], {'title': 'View 1',
'id_layer_vt': str(self.view_1.layer.name),
'style': {'type': 'circle',
'paint': {'circle-color': '#000', 'circle-radius': 8}},
'main': True})
self.assertDictEqual(data['map_layers'][1], {'title': self.relation_crud_view.name,
'id_layer_vt': f'relation-{self.view_1.layer.name}-relation_1',
'style': {},
'view_source': 'relation',
'pk': self.relation_crud_view.layer.pk,
'main': False})
self.assertDictEqual(data['map_layers'][2], {'title': 'extra geom 1',
'id_layer_vt': f'{self.view_1.layer.name}-extra-geom-1',
'style': {'paint': {'fill-color': '#000'}, 'type': 'fill'},
'view_source': 'extra_geometry',
'pk': self.extra_layer.pk,
'main': False})

def test_json_schema(self):
prop_country = CrudViewProperty.objects.create(view=self.view_1, key="country",
json_schema={'type': "string", "title": "Country"})
Expand Down
9 changes: 8 additions & 1 deletion terra_geocrud/thumbnail_backends.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import hashlib
import logging

from sorl.thumbnail.base import ThumbnailBackend
Expand Down Expand Up @@ -40,11 +41,17 @@ def get_thumbnail(self, file_, geometry_string, **options):
if value != getattr(default_settings, attr):
options.setdefault(key, value)

try:
source_image = default.engine.get_image(source)
options['hash'] = hashlib.md5(source_image.tobytes()).hexdigest()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use of insecure MD2, MD4, MD5, or SHA1 hash function.

except IOError:
pass

name = self._get_thumbnail_filename(source, geometry_string, options)
thumbnail = ImageFile(name, default.storage)
cached = default.kvstore.get(thumbnail)

if cached:
if cached and cached.exists():
return cached

# We have to check exists() because the Storage backend does not
Expand Down