diff options
Diffstat (limited to 'ishtar_common/serializers.py')
| -rw-r--r-- | ishtar_common/serializers.py | 130 | 
1 files changed, 106 insertions, 24 deletions
| diff --git a/ishtar_common/serializers.py b/ishtar_common/serializers.py index 187686321..e9b904d6f 100644 --- a/ishtar_common/serializers.py +++ b/ishtar_common/serializers.py @@ -1,3 +1,4 @@ +from collections import OrderedDict  from copy import deepcopy  import datetime  import json @@ -9,6 +10,7 @@ from rest_framework import serializers  from zipfile import ZipFile  from django.apps import apps +from django.conf import settings  from django.contrib.sites.models import Site  from django.core.serializers import deserialize, serialize @@ -72,11 +74,12 @@ def archive_serialization(result, archive_dir=None, archive=False,          )      if not archive_name.endswith(".zip"):          archive_name += ".zip" +    mode = "w" if archive_created else "a"      with tempfile.TemporaryDirectory() as tmpdirname:          if archive_dir:              os.mkdir(tmpdirname + os.sep + archive_dir) -        with ZipFile(archive_name, 'w') as current_zip: +        with ZipFile(archive_name, mode) as current_zip:              if archive_created:                  base_filename = "info.json"                  filename = tmpdirname + os.sep + base_filename @@ -86,19 +89,21 @@ def archive_serialization(result, archive_dir=None, archive=False,                      )                  current_zip.write(filename, arcname=base_filename) -            for model_name in result: +            for dir_name, model_name in result:                  base_filename = model_name + ".json"                  filename = tmpdirname + os.sep + base_filename                  with open(filename, "w") as json_file: -                    json_file.write(result[model_name]) -                current_zip.write(filename, -                                  arcname="types" + os.sep + base_filename) +                    json_file.write(result[(dir_name, model_name)]) +                arcname = base_filename +                if dir_name: +                    arcname = dir_name + os.sep + base_filename +                current_zip.write(filename, arcname=arcname)      return archive_name  def type_serialization(archive=False, return_empty_types=False,                         archive_name=None): -    result = {} +    result = OrderedDict()      for model in apps.get_models():          if not isinstance(model(), models.GeneralType):              continue @@ -113,9 +118,9 @@ def type_serialization(archive=False, return_empty_types=False,              recursion = "inverse_relation"          if recursion:              q = q.filter(**{recursion + "__isnull": True}) -        result[model_name] = serialize( -            "json", q.all(), -            indent=2, +        key = ("types", model_name) +        result[key] = serialize( +            "json", q.all(), indent=2,              use_natural_foreign_keys=True, use_natural_primary_keys=True          )          if recursion: @@ -126,9 +131,9 @@ def type_serialization(archive=False, return_empty_types=False,                  v = serialize(                      "json", q.all(), indent=2, use_natural_foreign_keys=True,                      use_natural_primary_keys=True) -                new_result = json.loads(result[model_name]) +                new_result = json.loads(result[key])                  new_result += json.loads(v) -                result[model_name] = json.dumps(new_result, indent=2) +                result[key] = json.dumps(new_result, indent=2)                  serialized += [item["id"] for item in q.values("id").all()]                  q = base_q.filter(**{recursion + "_id__in": serialized}                                    ).exclude(id__in=serialized) @@ -142,15 +147,78 @@ def type_serialization(archive=False, return_empty_types=False,                  result_cleaned = deepcopy(result_to_add)                  for res in result_cleaned:  # first add with no recursion                      res["fields"][recursion] = None -                new_result = json.loads(result[model_name]) +                new_result = json.loads(result[key])                  new_result += result_cleaned                  new_result += result_to_add -                result[model_name] = json.dumps(new_result, indent=2) +                result[key] = json.dumps(new_result, indent=2)      return archive_serialization(result, archive_dir="types", archive=archive,                                   return_empty_types=return_empty_types,                                   archive_name=archive_name) +def generic_get_results(model_list, dirname): +    result = OrderedDict() +    for model in model_list: +        model_name = model.__name__ +        model_name = str(model.__module__).split(".")[0] + "__" + model_name +        key = (dirname, model_name) +        result[key] = serialize( +            "json", model.objects.all(), +            indent=2, +            use_natural_foreign_keys=True, use_natural_primary_keys=True, +        ) +        if hasattr(model, "SERIALIZATION_EXCLUDE"): +            new_result = json.loads(result[key]) +            for idx in range(len(new_result)): +                for excluded_field in model.SERIALIZATION_EXCLUDE: +                    new_result[idx]["fields"].pop(excluded_field) +            result[key] = json.dumps(new_result) +    return result + + +def generic_archive_files(model_list, archive_name=None): +    result = [] +    for model in model_list: +        if hasattr(model, "SERIALIZATION_FILES"): +            for item in model.objects.all(): +                for attr in model.SERIALIZATION_FILES: +                    media = getattr(item, attr) +                    result.append((media.path, media.name)) + +    archive_created = False +    if not archive_name: +        archive_created = True +        tmpdir = tempfile.mkdtemp(prefix="ishtarexport-") + os.sep +        archive_name = tmpdir + "media.zip" +    if not archive_name.endswith(".zip"): +        archive_name += ".zip" +    mode = "w" if archive_created else "a" +    with ZipFile(archive_name, mode) as current_zip: +        for media_path, name in result: +            current_zip.write(media_path, arcname=name) +    return archive_name + + +CONF_MODEL_LIST = [ +    models.IshtarSiteProfile, models.GlobalVar, models.CustomForm, +    models.ExcludedField, models.JsonDataSection, models.JsonDataField, +    models.CustomFormJsonField, models.ImporterModel, +    models.DocumentTemplate +] + + +def conf_serialization(archive=False, return_empty_types=False, +                       archive_name=None): +    media_archive = generic_archive_files(CONF_MODEL_LIST) +    result = generic_get_results(CONF_MODEL_LIST, "common_conf") +    full_archive = archive_serialization( +        result, archive_dir="common_conf", archive=archive, +        return_empty_types=return_empty_types, archive_name=archive_name) +    with ZipFile(full_archive, 'a') as current_zip: +        current_zip.write(media_archive, arcname="media.zip") +    return full_archive + +  def restore_serialized(archive_name, delete_existing=False):      with zipfile.ZipFile(archive_name, "r") as zip_file:          # check version @@ -161,14 +229,28 @@ def restore_serialized(archive_name, delete_existing=False):                  "installation".format(info["serialize-version"])              ) -        # restore types -        for json_filename in zip_file.namelist(): -            path = json_filename.split(os.sep) -            if len(path) != 2 or path[0] != "types": -                continue -            if delete_existing: -                model = get_model_from_filename(path[-1]) -                model.objects.all().delete() -            data = zip_file.read(json_filename).decode("utf-8") -            for obj in deserialize("json", data): -                obj.save() +        DIRS = ( +            ("types", [None]), ("common_conf", CONF_MODEL_LIST) +        ) +        namelist = zip_file.namelist() +        for current_dir, model_list in DIRS: +            for current_model in model_list: +                for json_filename in namelist: +                    path = json_filename.split(os.sep) +                    if len(path) != 2 or path[0] != current_dir: +                        continue +                    model = get_model_from_filename(path[-1]) +                    if current_model and current_model != model: +                        continue +                    if delete_existing: +                        model.objects.all().delete() +                    data = zip_file.read(json_filename).decode("utf-8") +                    for obj in deserialize("json", data): +                        obj.save() +        # restore media +        if "media.zip" in namelist: +            with tempfile.TemporaryDirectory() as tmp_dir_name: +                zip_file.extract("media.zip", tmp_dir_name) +                with zipfile.ZipFile( +                        tmp_dir_name + os.sep + "media.zip", 'r') as media_zip: +                    media_zip.extractall(settings.MEDIA_ROOT)
\ No newline at end of file | 
