diff options
-rw-r--r-- | archaeological_operations/tests.py | 49 | ||||
-rw-r--r-- | ishtar_common/models_imports.py | 48 |
2 files changed, 86 insertions, 11 deletions
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py index 688af87ad..b8db7e2c7 100644 --- a/archaeological_operations/tests.py +++ b/archaeological_operations/tests.py @@ -4128,14 +4128,14 @@ class OperationExportMediaTest(TestCase, TestPermissionQuery, OperationInitTest) c.login(username=self.username, password=self.password) response = c.get(self.export_url) - self._test_files(response, [('image_00001.png', True)]) + self._test_files(response, [('operation_image_00001.png', True)]) self.exporter.files_to_export = 'A' self.exporter.save() response = c.get(self.export_url) self._test_files( response, - [('image_00001.png', True), ('file_00001.txt', False), ] + [('operation_image_00001.png', True), ('operation_file_00001.txt', False), ] ) self.exporter.thumbnail_for_images = True @@ -4143,7 +4143,50 @@ class OperationExportMediaTest(TestCase, TestPermissionQuery, OperationInitTest) response = c.get(self.export_url) self._test_files( response, - [('image_00001.jpg', True), ('file_00001.txt', False), ] + [('operation_image_00001.jpg', True), ('operation_file_00001.txt', False), ] + ) + + def _add_find(self): + cr_data = { + "label": "Context record", + "operation": self.operation, + "history_modifier": self.user, + } + ContextRecord = apps.get_model( + "archaeological_context_records", "ContextRecord" + ) + cr = ContextRecord.objects.create(**cr_data) + + BaseFind = apps.get_model("archaeological_finds", "BaseFind") + Find = apps.get_model("archaeological_finds", "Find") + + bf_data = { + "label": "Base find", + "history_modifier": self.get_default_user(), + "context_record": cr, + } + base_find = BaseFind.objects.create(**bf_data) + find = Find.objects.create( + history_modifier=self.get_default_user(), label="Find me" + ) + find.base_finds.add(base_find) + return cr, find + + def test_cascade_update(self): + self.exporter.cascade = True + self.exporter.save() + cr, find = self._add_find() + cr.documents.add(self.documents[0]) + find.documents.add(self.documents[0]) + c = Client() + c.login(username=self.username, password=self.password) + + response = c.get(self.export_url) + self._test_files( + response, + [('operation_image_00001.png', True), + ('contextrecord_image_00001.png', True), + ('find_image_00001.png', True),] ) diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py index 175d2f25b..0157b33ee 100644 --- a/ishtar_common/models_imports.py +++ b/ishtar_common/models_imports.py @@ -3115,6 +3115,19 @@ class MediaExporter(models.Model): return True return False + def _get_down_objects(self, obj_list): + if not obj_list: + return [] + down = [] + for o in obj_list: + if o.SLUG == "basefind": + attrs = ["find"] + else: + attrs = getattr(o, "DOWN_MODEL_UPDATE", []) + for attr in attrs: + down += list(getattr(o, attr).all()) + return down + def export(self, obj, tmpdir=None): if not tmpdir: tmpdir = tempfile.mkdtemp() @@ -3138,7 +3151,26 @@ class MediaExporter(models.Model): media_attrs.append("associated_file") archive_path = os.path.join(tmpdir, "archive") os.mkdir(archive_path) - for idx, document in enumerate(obj.documents.filter(q).all()): + items = [obj] + if self.cascade: + down = self._get_down_objects([obj]) + items += down + while down: + down = self._get_down_objects(down) + items += down + counters = {} + for item in items: + if not hasattr(item, "documents"): + continue + self._copy_media(item, q, media_attrs, counters, archive_path) + now = datetime.datetime.now() + archive_name = os.path.join(tmpdir, f"media-{now.strftime('%Y-%m-%d-%H%M%S')}") + shutil.make_archive(archive_name, "zip", archive_path) + return archive_name + ".zip" + + def _copy_media(self, item, q, media_attrs, counters, archive_path): + item_type = item.SLUG + for idx, document in enumerate(item.documents.filter(q).all()): for media_attr in media_attrs: media = getattr(document, media_attr) if not media or not media.path or not os.path.exists(media.path): @@ -3150,12 +3182,12 @@ class MediaExporter(models.Model): name = base_name else: if media_attr == "associated_file": - name = "file" + name = f"{item_type}_file" else: - name = "image" - name += f"_{idx + 1:05d}.{ext}" + name = f"{item_type}_image" + key = (item_type, media_attr) + if key not in counters: + counters[key] = 0 + counters[key] += 1 + name += f"_{idx + counters[key]:05d}.{ext}" shutil.copy(media.path, os.path.join(archive_path, name)) - now = datetime.datetime.now() - archive_name = os.path.join(tmpdir, f"media-{now.strftime('%Y-%m-%d-%H%M%S')}") - shutil.make_archive(archive_name, "zip", archive_path) - return archive_name + ".zip" |