diff options
Diffstat (limited to 'ishtar_common/models_imports.py')
| -rw-r--r-- | ishtar_common/models_imports.py | 103 | 
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  | 
