From 5ba98704bd2c936a991ad9452330792fbd5f12ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Mon, 19 Jun 2017 16:14:48 +0200 Subject: [PATCH] general: add import/export of map layers (#16706) --- combo/apps/maps/models.py | 28 ++++++++++++++++++++++++++++ combo/data/utils.py | 10 ++++++++-- tests/test_import_export.py | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/combo/apps/maps/models.py b/combo/apps/maps/models.py index 5de2546..093dbc5 100644 --- a/combo/apps/maps/models.py +++ b/combo/apps/maps/models.py @@ -14,7 +14,9 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import json +from django.core import serializers from django.db import models from django.utils.text import slugify from django.utils.translation import ugettext_lazy as _ @@ -86,6 +88,32 @@ class MapLayer(models.Model): def __unicode__(self): return self.label + def natural_key(self): + return (self.slug, ) + + @classmethod + def export_all_for_json(cls): + return [x.get_as_serialized_object() for x in MapLayer.objects.all()] + + def get_as_serialized_object(self): + serialized_layer = json.loads(serializers.serialize('json', [self], + use_natural_foreign_keys=True, use_natural_primary_keys=True))[0] + del serialized_layer['model'] + return serialized_layer + + @classmethod + def load_serialized_objects(cls, json_site): + for json_layer in json_site: + cls.load_serialized_object(json_layer) + + @classmethod + def load_serialized_object(cls, json_layer): + json_layer['model'] = 'maps.maplayer' + layer, created = MapLayer.objects.get_or_create(slug=json_layer['fields']['slug']) + json_layer['pk'] = layer.id + layer = [x for x in serializers.deserialize('json', json.dumps([json_layer]))][0] + layer.save() + def get_geojson(self, request): response = requests.get(self.geojson_url, remote_service='auto', diff --git a/combo/data/utils.py b/combo/data/utils.py index 85c93da..2dbf75b 100644 --- a/combo/data/utils.py +++ b/combo/data/utils.py @@ -16,18 +16,21 @@ from django.db import transaction +from combo.apps.maps.models import MapLayer from .models import Page def export_site(): '''Dump site objects to JSON-dumpable dictionnary''' - return {'pages': Page.export_all_for_json()} + return {'pages': Page.export_all_for_json(), + 'map-layers': MapLayer.export_all_for_json()} def import_site(data, if_empty=False, clean=False): - if if_empty and Page.objects.count(): + if if_empty and (Page.objects.count() or MapLayer.objects.count()): return if clean: + MapLayer.objects.all().delete() Page.objects.all().delete() if isinstance(data, list): @@ -36,4 +39,7 @@ def import_site(data, if_empty=False, clean=False): data = {'pages': data} with transaction.atomic(): + MapLayer.load_serialized_objects(data.get('map-layers') or []) + + with transaction.atomic(): Page.load_serialized_pages(data.get('pages') or []) diff --git a/tests/test_import_export.py b/tests/test_import_export.py index 15e54a1..cdeba07 100644 --- a/tests/test_import_export.py +++ b/tests/test_import_export.py @@ -9,6 +9,7 @@ import tempfile import pytest from django.core.management import call_command +from combo.apps.maps.models import MapLayer from combo.data.models import Page, TextCell from combo.data.utils import export_site, import_site @@ -26,6 +27,10 @@ def some_data(): cell = TextCell(page=page, order=0, text='hello world') cell.save() +@pytest.fixture +def some_map_layers(): + MapLayer(label='Foo', slug='foo', geojson_url='http://example.net/foo/').save() + MapLayer(label='Bar', slug='bar', geojson_url='http://example.net/bar/').save() def get_output_of_command(command, *args, **kwargs): old_stdout = sys.stdout @@ -76,3 +81,31 @@ def test_backward_compatibility_import(app, some_data): Page.objects.all().delete() import_site(data=old_export) assert Page.objects.count() == 3 + +def test_import_export_map_layers(app, some_map_layers): + output = get_output_of_command('export_site') + assert len(json.loads(output)['map-layers']) == 2 + import_site(data={}, clean=True) + assert MapLayer.objects.all().count() == 0 + empty_output = get_output_of_command('export_site') + assert len(json.loads(empty_output)['map-layers']) == 0 + + MapLayer(label='Baz', slug='baz', geojson_url='http://example.net/baz/').save() + old_stdin = sys.stdin + sys.stdin = StringIO(json.dumps({})) + assert MapLayer.objects.count() == 1 + try: + call_command('import_site', '-', clean=True) + finally: + sys.stdin = old_stdin + assert MapLayer.objects.count() == 0 + + with tempfile.NamedTemporaryFile() as f: + f.write(output) + f.flush() + call_command('import_site', f.name) + + assert MapLayer.objects.count() == 2 + + import_site(data={}, if_empty=True) + assert MapLayer.objects.count() == 2 -- 2.11.0