From 346aae9242cd725b3e14c3e49e7999b851698e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Fri, 6 Jul 2018 14:17:06 +0200 Subject: [PATCH 2/2] maps: add option to specify properties to include in geojson (#25094) --- .../migrations/0007_auto_20180706_1345.py | 20 ++++ combo/apps/maps/models.py | 19 +++- combo/apps/maps/static/js/combo.map.js | 6 +- tests/test_maps_cells.py | 105 +++++++++++++++++- 4 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 combo/apps/maps/migrations/0007_auto_20180706_1345.py diff --git a/combo/apps/maps/migrations/0007_auto_20180706_1345.py b/combo/apps/maps/migrations/0007_auto_20180706_1345.py new file mode 100644 index 0000000..494cffb --- /dev/null +++ b/combo/apps/maps/migrations/0007_auto_20180706_1345.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.12 on 2018-07-06 11:45 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('maps', '0006_auto_20180627_0841'), + ] + + operations = [ + migrations.AddField( + model_name='maplayer', + name='properties', + field=models.CharField(blank=True, help_text='List of properties', max_length=500, verbose_name='Properties'), + ), + ] diff --git a/combo/apps/maps/models.py b/combo/apps/maps/models.py index cce3426..3e566c3 100644 --- a/combo/apps/maps/models.py +++ b/combo/apps/maps/models.py @@ -102,6 +102,8 @@ class MapLayer(models.Model): include_user_identifier = models.BooleanField( _('Include user identifier in request'), default=True) + properties = models.CharField(_('Properties'), max_length=500, blank=True, + help_text=_('List of properties')) class Meta: ordering = ('label',) @@ -165,6 +167,20 @@ class MapLayer(models.Model): else: features = data + properties = [] + if self.properties: + properties = [x.strip() for x in self.properties.split(',')] + for feature in features: + if 'display_fields' in feature['properties']: + # w.c.s. content, filter fields on varnames + feature['properties']['display_fields'] = [ + x for x in feature['properties']['display_fields'] + if x.get('varname') in properties] + else: + # classic geojson, filter properties + feature['properties'] = dict( + [x for x in feature['properties'].items() if x[0] in properties]) + if request and request.GET.get('distance'): distance = float(request.GET['distance']) center_lat = float(request.GET['lat']) @@ -202,7 +218,8 @@ class MapLayer(models.Model): 'icon_colour': self.icon_colour, 'label': self.label, 'icon': self.icon, - 'identifier': self.slug + 'identifier': self.slug, + 'properties': properties, } return features diff --git a/combo/apps/maps/static/js/combo.map.js b/combo/apps/maps/static/js/combo.map.js index cdc8399..ec9b2db 100644 --- a/combo/apps/maps/static/js/combo.map.js +++ b/combo/apps/maps/static/js/combo.map.js @@ -32,8 +32,12 @@ $(function() { popup += $popup_field.html(); }); } else { + var ordered_keys = feature.properties.layer.properties; + if (! ordered_keys) { + ordered_keys = Object.keys(properties).sort(); + } var properties = feature.properties; - $.each(Object.keys(properties).sort(), function(idx, field) { + $.each(ordered_keys, function(idx, field) { // exclude object type properties if (typeof(properties[field]) !== 'object') { var $popup_field = $('
'); diff --git a/tests/test_maps_cells.py b/tests/test_maps_cells.py index dc2099e..75e18cd 100644 --- a/tests/test_maps_cells.py +++ b/tests/test_maps_cells.py @@ -22,7 +22,8 @@ SAMPLE_GEOJSON_CONTENT = '''{ { "type": "Feature", "properties": { - "name": "Foo" + "name": "Foo", + "extra": "Baz" }, "geometry": { "type": "Point", @@ -35,7 +36,8 @@ SAMPLE_GEOJSON_CONTENT = '''{ { "type": "Feature", "properties": { - "name": "Bar" + "name": "Bar", + "extra": "Baz" }, "geometry": { "type": "Point", @@ -48,6 +50,43 @@ SAMPLE_GEOJSON_CONTENT = '''{ ] }''' +SAMPLE_WCS_GEOJSON_CONTENT = '''{ + "type": "FeatureCollection", + "features": [ + { + "type" : "Feature", + "geometry" : { + "type" : "Point", + "coordinates" : [ + 6.175303, + 48.684512 + ] + }, + "properties" : { + "name" : "Test - n°144-4", + "view_label" : "Voir", + "status_name" : "Foo", + "display_fields" : [ + { + "varname" : "id", + "html_value" : "144-4", + "value" : "144-4", + "label" : "Numéro" + }, + { + "varname" : null, + "html_value" : "toto", + "value" : "toto", + "label" : "toto" + } + ] + } + } + ] +}''' + + + @pytest.fixture def user(): try: @@ -243,3 +282,65 @@ def test_get_geojson(layer, user): resp = client.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id}) + '?lng=2.54&lat=48.84&distance=100') assert len(json.loads(resp.content)['features']) == 0 + +def test_get_geojson_properties(layer, user): + page = Page(title='xxx', slug='new', template_name='standard') + page.save() + cell = Map(page=page, placeholder='content', order=0, public=True) + cell.title = 'Map' + cell.save() + layer.save() + cell.layers.add(layer) + + with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get: + layer.geojson_url = 'http://example.org/geojson?t1' + layer.save() + requests_get.return_value = mock.Mock( + content=SAMPLE_GEOJSON_CONTENT, + json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT), + status_code=200) + resp = client.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id})) + features = json.loads(resp.content)['features'] + assert 'name' in features[0]['properties'] + assert 'extra' in features[0]['properties'] + assert features[0]['properties']['layer']['properties'] == [] + + with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get: + layer.geojson_url = 'http://example.org/geojson?t2' + layer.properties = 'name, hop' + layer.save() + requests_get.return_value = mock.Mock( + content=SAMPLE_GEOJSON_CONTENT, + json=lambda: json.loads(SAMPLE_GEOJSON_CONTENT), + status_code=200) + resp = client.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id})) + features = json.loads(resp.content)['features'] + assert 'name' in features[0]['properties'] + assert 'extra' not in features[0]['properties'] + assert features[0]['properties']['layer']['properties'] == ['name', 'hop'] + + with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get: + layer.geojson_url = 'http://example.org/geojson?t3' + layer.properties = '' + layer.save() + requests_get.return_value = mock.Mock( + content=SAMPLE_WCS_GEOJSON_CONTENT, + json=lambda: json.loads(SAMPLE_WCS_GEOJSON_CONTENT), + status_code=200) + resp = client.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id})) + features = json.loads(resp.content)['features'] + assert len(features[0]['properties']['display_fields']) == 2 + assert features[0]['properties']['layer']['properties'] == [] + + with mock.patch('combo.utils.requests_wrapper.RequestsSession.request') as requests_get: + layer.geojson_url = 'http://example.org/geojson?t4' + layer.properties = 'id' + layer.save() + requests_get.return_value = mock.Mock( + content=SAMPLE_WCS_GEOJSON_CONTENT, + json=lambda: json.loads(SAMPLE_WCS_GEOJSON_CONTENT), + status_code=200) + resp = client.get(reverse('mapcell-geojson', kwargs={'cell_id': cell.id})) + features = json.loads(resp.content)['features'] + assert len(features[0]['properties']['display_fields']) == 1 + assert features[0]['properties']['layer']['properties'] == ['id'] -- 2.18.0