general: add import/export of map layers (#16706)

This commit is contained in:
Frédéric Péters 2017-06-19 16:14:48 +02:00
parent 0e44c38f0c
commit 3eb6d93882
3 changed files with 69 additions and 2 deletions

View File

@ -14,7 +14,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
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 _
@ -85,6 +87,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',

View File

@ -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):
@ -35,5 +38,8 @@ def import_site(data, if_empty=False, clean=False):
# format.
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 [])

View File

@ -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