0001-general-add-import-export-of-map-layers-16706.patch
combo/apps/maps/models.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU Affero General Public License |
15 | 15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
import json |
|
17 | 18 | |
19 |
from django.core import serializers |
|
18 | 20 |
from django.db import models |
19 | 21 |
from django.utils.text import slugify |
20 | 22 |
from django.utils.translation import ugettext_lazy as _ |
... | ... | |
86 | 88 |
def __unicode__(self): |
87 | 89 |
return self.label |
88 | 90 | |
91 |
def natural_key(self): |
|
92 |
return (self.slug, ) |
|
93 | ||
94 |
@classmethod |
|
95 |
def export_all_for_json(cls): |
|
96 |
return [x.get_as_serialized_object() for x in MapLayer.objects.all()] |
|
97 | ||
98 |
def get_as_serialized_object(self): |
|
99 |
serialized_layer = json.loads(serializers.serialize('json', [self], |
|
100 |
use_natural_foreign_keys=True, use_natural_primary_keys=True))[0] |
|
101 |
del serialized_layer['model'] |
|
102 |
return serialized_layer |
|
103 | ||
104 |
@classmethod |
|
105 |
def load_serialized_objects(cls, json_site): |
|
106 |
for json_layer in json_site: |
|
107 |
cls.load_serialized_object(json_layer) |
|
108 | ||
109 |
@classmethod |
|
110 |
def load_serialized_object(cls, json_layer): |
|
111 |
json_layer['model'] = 'maps.maplayer' |
|
112 |
layer, created = MapLayer.objects.get_or_create(slug=json_layer['fields']['slug']) |
|
113 |
json_layer['pk'] = layer.id |
|
114 |
layer = [x for x in serializers.deserialize('json', json.dumps([json_layer]))][0] |
|
115 |
layer.save() |
|
116 | ||
89 | 117 |
def get_geojson(self, request): |
90 | 118 |
response = requests.get(self.geojson_url, |
91 | 119 |
remote_service='auto', |
combo/data/utils.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
from django.db import transaction |
18 | 18 | |
19 |
from combo.apps.maps.models import MapLayer |
|
19 | 20 |
from .models import Page |
20 | 21 | |
21 | 22 |
def export_site(): |
22 | 23 |
'''Dump site objects to JSON-dumpable dictionnary''' |
23 |
return {'pages': Page.export_all_for_json()} |
|
24 |
return {'pages': Page.export_all_for_json(), |
|
25 |
'map-layers': MapLayer.export_all_for_json()} |
|
24 | 26 | |
25 | 27 | |
26 | 28 |
def import_site(data, if_empty=False, clean=False): |
27 |
if if_empty and Page.objects.count():
|
|
29 |
if if_empty and (Page.objects.count() or MapLayer.objects.count()):
|
|
28 | 30 |
return |
29 | 31 | |
30 | 32 |
if clean: |
33 |
MapLayer.objects.all().delete() |
|
31 | 34 |
Page.objects.all().delete() |
32 | 35 | |
33 | 36 |
if isinstance(data, list): |
... | ... | |
36 | 39 |
data = {'pages': data} |
37 | 40 | |
38 | 41 |
with transaction.atomic(): |
42 |
MapLayer.load_serialized_objects(data.get('map-layers') or []) |
|
43 | ||
44 |
with transaction.atomic(): |
|
39 | 45 |
Page.load_serialized_pages(data.get('pages') or []) |
tests/test_import_export.py | ||
---|---|---|
9 | 9 |
import pytest |
10 | 10 |
from django.core.management import call_command |
11 | 11 | |
12 |
from combo.apps.maps.models import MapLayer |
|
12 | 13 |
from combo.data.models import Page, TextCell |
13 | 14 |
from combo.data.utils import export_site, import_site |
14 | 15 | |
... | ... | |
26 | 27 |
cell = TextCell(page=page, order=0, text='hello world') |
27 | 28 |
cell.save() |
28 | 29 | |
30 |
@pytest.fixture |
|
31 |
def some_map_layers(): |
|
32 |
MapLayer(label='Foo', slug='foo', geojson_url='http://example.net/foo/').save() |
|
33 |
MapLayer(label='Bar', slug='bar', geojson_url='http://example.net/bar/').save() |
|
29 | 34 | |
30 | 35 |
def get_output_of_command(command, *args, **kwargs): |
31 | 36 |
old_stdout = sys.stdout |
... | ... | |
76 | 81 |
Page.objects.all().delete() |
77 | 82 |
import_site(data=old_export) |
78 | 83 |
assert Page.objects.count() == 3 |
84 | ||
85 |
def test_import_export_map_layers(app, some_map_layers): |
|
86 |
output = get_output_of_command('export_site') |
|
87 |
assert len(json.loads(output)['map-layers']) == 2 |
|
88 |
import_site(data={}, clean=True) |
|
89 |
assert MapLayer.objects.all().count() == 0 |
|
90 |
empty_output = get_output_of_command('export_site') |
|
91 |
assert len(json.loads(empty_output)['map-layers']) == 0 |
|
92 | ||
93 |
MapLayer(label='Baz', slug='baz', geojson_url='http://example.net/baz/').save() |
|
94 |
old_stdin = sys.stdin |
|
95 |
sys.stdin = StringIO(json.dumps({})) |
|
96 |
assert MapLayer.objects.count() == 1 |
|
97 |
try: |
|
98 |
call_command('import_site', '-', clean=True) |
|
99 |
finally: |
|
100 |
sys.stdin = old_stdin |
|
101 |
assert MapLayer.objects.count() == 0 |
|
102 | ||
103 |
with tempfile.NamedTemporaryFile() as f: |
|
104 |
f.write(output) |
|
105 |
f.flush() |
|
106 |
call_command('import_site', f.name) |
|
107 | ||
108 |
assert MapLayer.objects.count() == 2 |
|
109 | ||
110 |
import_site(data={}, if_empty=True) |
|
111 |
assert MapLayer.objects.count() == 2 |
|
79 |
- |