summaryrefslogtreecommitdiff
path: root/ishtar_common/models_imports.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2021-02-22 12:13:51 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2021-02-28 12:15:24 +0100
commitdea298e5a607e483ae5f75e47e92b35330e330af (patch)
tree04b196b80ad2cd569175ac0565576f9200ea9f6e /ishtar_common/models_imports.py
parentfeae86528cba80ae9f0bcb189451ee3fb02d88be (diff)
downloadIshtar-dea298e5a607e483ae5f75e47e92b35330e330af.tar.bz2
Ishtar-dea298e5a607e483ae5f75e47e92b35330e330af.zip
Zip/unzip files on archive/unarchive imports
Diffstat (limited to 'ishtar_common/models_imports.py')
-rw-r--r--ishtar_common/models_imports.py103
1 files changed, 100 insertions, 3 deletions
diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py
index 7a8a10bc2..5a3af1a05 100644
--- a/ishtar_common/models_imports.py
+++ b/ishtar_common/models_imports.py
@@ -19,6 +19,7 @@
import csv
import datetime
+import json
import os
import logging
import shutil
@@ -26,9 +27,11 @@ import re
import tempfile
import zipfile
+from django.apps import apps
from django.conf import settings
from django.contrib.gis.db import models
from django.core.exceptions import ValidationError
+from django.core.files import File
from django.core.files.base import ContentFile
from django.core.validators import validate_comma_separated_integer_list
from django.db.models.base import ModelBase
@@ -965,6 +968,9 @@ class Import(models.Model):
match_file = models.FileField(
_("Match file"), upload_to="upload/imports/%Y/%m/", blank=True,
null=True, max_length=255, help_text=max_size_help())
+ archive_file = models.FileField(
+ _("Archive file"), upload_to="upload/imports/%Y/%m/", blank=True,
+ null=True, max_length=255, help_text=max_size_help())
state = models.CharField(_("State"), max_length=2, choices=IMPORT_STATE,
default='C')
conservative_import = models.BooleanField(
@@ -1096,7 +1102,7 @@ class Import(models.Model):
"""
Get available action relevant with the current status
"""
- from ishtar_common.models import IshtarSiteProfile
+ IshtarSiteProfile = apps.get_model("ishtar_common", "IshtarSiteProfile")
profile = IshtarSiteProfile.get_current_profile()
actions = []
if self.state == 'C':
@@ -1121,7 +1127,8 @@ class Import(models.Model):
actions.append(('CH', _("Check for changes")))
actions.append(('AC', _("Archive")))
if self.state == 'AC':
- actions.append(('A', _("Unarchive")))
+ state = "FE" if self.error_file else "F"
+ actions.append((state, _("Unarchive")))
actions.append(('D', _("Delete")))
return actions
@@ -1357,10 +1364,94 @@ class Import(models.Model):
if return_importer_and_data:
return importer, data
+ def _unarchive(self):
+ if not self.archive_file:
+ return
+ with tempfile.TemporaryDirectory() as tmp_dir_name:
+ # extract the current archive
+ current_zip = zipfile.ZipFile(self.archive_file.path, 'r')
+ name_list = current_zip.namelist()
+ if "content.json" not in name_list:
+ return
+ for name in name_list:
+ current_zip.extract(name, tmp_dir_name)
+ current_zip.close()
+ content_name = os.path.join(tmp_dir_name, "content.json")
+ try:
+ with open(content_name, "r") as content:
+ files = json.loads(content.read())
+ except (IOError, json.JSONDecodeError):
+ return
+ today = datetime.date.today()
+ for attr in files:
+ filename = files[attr]
+ full_filename = os.path.join(tmp_dir_name, filename)
+ with open(full_filename, "rb") as raw_file:
+ getattr(self, attr).save(
+ "upload/imports/{}/{:02d}/{}".format(
+ today.year, today.month, filename),
+ File(raw_file)
+ )
+
+ os.remove(self.archive_file.path)
+ setattr(self, 'archive_file', None)
+ self.state = "FE" if self.error_file else "F"
+ self.save()
+ return True
+
+ def _archive(self):
+ file_attr = ["imported_file", "error_file", "result_file",
+ "match_file"]
+ files = [
+ (k, getattr(self, k).path, getattr(self, k).name.split(os.sep)[-1])
+ for k in file_attr
+ if getattr(self, k)
+ ]
+ self._archive_pending = True
+ with tempfile.TemporaryDirectory() as tmpdir:
+ base_name = "{}.zip".format(slugify(self.name))
+ archive_name = os.path.join(tmpdir, base_name)
+ with zipfile.ZipFile(archive_name, "w") as current_zip:
+ zip_content = {}
+ for k, path, name in files:
+ try:
+ current_zip.write(path, arcname=name)
+ zip_content[k] = name
+ except OSError:
+ pass
+ content_name = os.path.join(tmpdir, "content.json")
+ with open(content_name, "w") as content:
+ content.write(json.dumps(zip_content))
+ current_zip.write(content_name, arcname="content.json")
+
+ today = datetime.date.today()
+ with open(archive_name, "rb", ) as raw_file:
+ self.archive_file.save(
+ "upload/imports/{}/{:02d}/{}".format(
+ today.year, today.month, base_name),
+ File(raw_file)
+ )
+ IshtarSiteProfile = apps.get_model("ishtar_common", "IshtarSiteProfile")
+ profile = IshtarSiteProfile.get_current_profile()
+ if profile.delete_image_zip_on_archive:
+ file_attr.append("imported_images")
+ for attr in file_attr:
+ file_field = getattr(self, attr)
+ if file_field:
+ os.remove(file_field.path)
+ setattr(self, attr, None)
+ self.save()
+ self._archive_pending = False
+
def archive(self):
self.state = 'AC'
self.end_date = datetime.datetime.now()
- self.save()
+ self._archive()
+
+ def unarchive(self, state):
+ if not self._unarchive():
+ self.state = state
+ self.save() # only save if no save previously
def get_all_imported(self):
imported = []
@@ -1370,6 +1461,12 @@ class Import(models.Model):
for obj in getattr(self, accessor).all()]
return imported
+ def save(self, *args, **kwargs):
+ super(Import, self).save(*args, **kwargs)
+ if self.state == "AC" and not getattr(
+ self, "_archive_pending", False) and not self.archive_file:
+ self._archive()
+
def pre_delete_import(sender, **kwargs):
# deleted imported items when an import is delete