Projet

Général

Profil

0001-opengis-add-feature-queries-20535.patch

Serghei Mihai (congés, retour 15/05), 12 décembre 2017 17:54

Télécharger (14,6 ko)

Voir les différences:

Subject: [PATCH] opengis: add feature queries (#20535)

 passerelle/apps/opengis/forms.py                   | 30 +++++++++++
 .../opengis/migrations/0003_auto_20171212_1620.py  | 33 ++++++++++++
 passerelle/apps/opengis/models.py                  | 57 +++++++++++++++++++++
 .../opengis/featurequery_confirm_delete.html       | 25 +++++++++
 .../templates/opengis/featurequery_form.html       | 33 ++++++++++++
 .../opengis/templates/opengis/opengis_detail.html  | 38 ++++++++++++++
 passerelle/apps/opengis/urls.py                    | 28 ++++++++++
 passerelle/apps/opengis/views.py                   | 59 ++++++++++++++++++++++
 8 files changed, 303 insertions(+)
 create mode 100644 passerelle/apps/opengis/forms.py
 create mode 100644 passerelle/apps/opengis/migrations/0003_auto_20171212_1620.py
 create mode 100644 passerelle/apps/opengis/templates/opengis/featurequery_confirm_delete.html
 create mode 100644 passerelle/apps/opengis/templates/opengis/featurequery_form.html
 create mode 100644 passerelle/apps/opengis/templates/opengis/opengis_detail.html
 create mode 100644 passerelle/apps/opengis/urls.py
 create mode 100644 passerelle/apps/opengis/views.py
passerelle/apps/opengis/forms.py
1
# passerelle - uniform access to multiple data sources and services
2
# Copyright (C) 2016 Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django import forms
18

  
19
from .models import FeatureQuery
20

  
21

  
22
class FeatureQueryForm(forms.ModelForm):
23
    class Meta:
24
        model = FeatureQuery
25
        widgets = {
26
            'resource': forms.HiddenInput(),
27
            'query_filters': forms.Textarea(attrs={'rows': 2}),
28
            'response_filters': forms.Textarea(attrs={'rows': 2}),
29
        }
30
        fields = '__all__'
passerelle/apps/opengis/migrations/0003_auto_20171212_1620.py
1
# -*- coding: utf-8 -*-
2
from __future__ import unicode_literals
3

  
4
from django.db import migrations, models
5

  
6

  
7
class Migration(migrations.Migration):
8

  
9
    dependencies = [
10
        ('opengis', '0002_auto_20171129_1814'),
11
    ]
12

  
13
    operations = [
14
        migrations.CreateModel(
15
            name='FeatureQuery',
16
            fields=[
17
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
18
                ('slug', models.SlugField(verbose_name='Name (slug)')),
19
                ('label', models.CharField(max_length=100, verbose_name='Label')),
20
                ('description', models.TextField(verbose_name='Description', blank=True)),
21
                ('query_filters', models.TextField(help_text='List of filters (name:expression)', verbose_name='Query Filters', blank=True)),
22
                ('response_filters', models.TextField(help_text='List of filters (name:expression)', verbose_name='Response Filters', blank=True)),
23
            ],
24
            options={
25
                'ordering': ['slug'],
26
            },
27
        ),
28
        migrations.AddField(
29
            model_name='featurequery',
30
            name='resource',
31
            field=models.ForeignKey(to='opengis.OpenGIS'),
32
        ),
33
    ]
passerelle/apps/opengis/models.py
43 43
    return d
44 44

  
45 45

  
46
class FeatureQuery(models.Model):
47
    resource = models.ForeignKey('OpenGIS')
48
    slug = models.SlugField(_('Name (slug)'))
49
    label = models.CharField(_('Label'), max_length=100)
50
    description = models.TextField(_('Description'), blank=True)
51
    query_filters = models.TextField(_('Query Filters'), blank=True,
52
            help_text=_('List of filters (name:expression)'))
53
    response_filters = models.TextField(_('Response Filters'), blank=True,
54
            help_text=_('List of filters (name:expression)'))
55

  
56
    class Meta:
57
        ordering = ['slug']
58

  
59
    def get_list(self, attribute):
60
        if not getattr(self, attribute):
61
            return []
62
        return getattr(self, attribute).strip().splitlines()
63

  
64
    def process_query_filters(self, params):
65
        filters = {}
66
        for filter_line in self.get_list('query_filters'):
67
            name, value = filter_line.split(':', 1)
68
            filters[name] = eval(value.strip(), {}, params)
69
        return filters
70

  
71
    def process_response_filters(self, features):
72
        filters = self.get_list('response_filters')
73
        if not filters:
74
            return features
75

  
76
        result = []
77
        for feature in features:
78
            filtered_feature = {}
79
            for line in filters:
80
                name, value = line.split(':', 1)
81
                filtered_feature[name] = eval(value.strip(), {}, feature)
82
            result.append(filtered_feature)
83
        return result
84

  
85

  
46 86
class OpenGIS(BaseResource):
47 87
    category = _('Geographic information system')
48 88
    wms_service_url = models.URLField(_('Web Map Service (WMS) URL'), max_length=256, blank=True)
......
106 146
            data.append(feature)
107 147
        return {'data': data}
108 148

  
149
    @endpoint(perm='can_access', methods=['get'],
150
              name='feature', pattern='^(?P<query_name>[\w-]+)/$')
151
    def feature_query(self, request, query_name, **kwargs):
152
        try:
153
            query = FeatureQuery.objects.get(resource=self.id, slug=query_name)
154
        except Query.DoesNotExist:
155
            raise APIError(u'no such query')
156
        params = {
157
            'VERSION': self.get_wfs_service_version(),
158
            'SERVICE': 'WFS',
159
            'REQUEST': 'GetFeature',
160
            'OUTPUTFORMAT': 'json',
161
        }
162
        params.update(query.process_query_filters(request.GET.dict()))
163
        response = self.requests.get(self.wfs_service_url, params=params)
164
        data = query.process_response_filters(response.json()['features'])
165
        return {'data': data}
109 166

  
110 167
    @endpoint(perm='can_access',
111 168
              description=_('Get feature info'),
passerelle/apps/opengis/templates/opengis/featurequery_confirm_delete.html
1
{% extends "passerelle/manage.html" %}
2
{% load i18n %}
3

  
4
{% block breadcrumb %}
5
{{ block.super }}
6
<a href="{{ resource.get_absolute_url }}">{{ resource.title }}</a>
7
<a href="{{ object.id }}">{{ object.slug }}</a>
8
{% endblock %}
9

  
10
{% block appbar %}
11
<h2>{% trans 'Feature Query:' %} {{ object.slug }}</h2>
12
{% endblock %}
13

  
14
{% block content %}
15

  
16
<form method="post">
17
  {% csrf_token %}
18
  <p>{% blocktrans %}Are you sure you want to delete this feature query?{% endblocktrans %}</p>
19
  <div class="buttons">
20
    <button class="delete-button">{% trans 'Delete' %}</button>
21
    <a href="{{ resource.get_absolute_url }}" class="cancel">{% trans 'Cancel' %}</a>
22
  </div>
23
</form>
24

  
25
{% endblock %}
passerelle/apps/opengis/templates/opengis/featurequery_form.html
1
{% extends "passerelle/manage.html" %}
2
{% load i18n %}
3

  
4
{% block breadcrumb %}
5
{{ block.super }}
6
<a href="{{ resource.get_absolute_url }}">{{ resource.title }}</a>
7
{% if object.id %}
8
<a href="{{ object.id }}">{{ object.slug }}</a>
9
{% else %}
10
<a href="#">{% trans 'Add Feature Query' %}</a>
11
{% endif %}
12
{% endblock %}
13

  
14
{% block appbar %}
15
<h2>{% if object.id %}{% trans 'Feature Query:' %} {{ object.slug }}{% else %}{% trans 'New Feature Query' %}{% endif %}</h2>
16
{% endblock %}
17

  
18
{% block content %}
19

  
20
 <form method="post" enctype="multipart/form-data">
21
   <div id="form-content">
22
     {% csrf_token %}
23
     {{ form.as_p }}
24
   </div>
25
   {% block buttons %}
26
   <div class="buttons">
27
     <button class="submit-button">{% trans "Save" %}</button>
28
     <a class="cancel" href="{{ resource.get_absolute_url }}">{% trans 'Cancel' %}</a>
29
   </div>
30
   {% endblock %}
31
 </form>
32

  
33
{% endblock %}
passerelle/apps/opengis/templates/opengis/opengis_detail.html
1
{% extends "passerelle/manage/service_view.html" %}
2
{% load i18n passerelle %}
3

  
4
{% block endpoints %}
5
{{ block.super }}
6
<ul>
7
  {% for query in object.featurequery_set.all %}
8
  <li>{{ query.label }}:
9
    {% url 'generic-endpoint' connector='opengis' slug=object.slug endpoint='feature' rest=query.slug as query_url %}
10
    <a href="{{ query_url }}/">{{ query_url }}/</a>
11
    {% if query.description %}&mdash; {{ query.description }}{% endif %}
12
  </li>
13
  {% endfor %}
14
  </ul>
15

  
16
{% if object|can_edit:request.user %}
17
<div id="queries">
18
<h3>{% trans 'Feature queries' %}</h3>
19
<div>
20
{% if object.featurequery_set.count %}
21
<ul class="objects-list single-links">
22
{% for query in object.featurequery_set.all %}
23
  <li><a href="{% url 'opengis-edit-featurequery' connector_slug=object.slug pk=query.id %}">{{ query.slug }}</a>
24
      <a rel="popup" class="delete" href="{% url 'opengis-delete-featurequery' connector_slug=object.slug pk=query.id %}">{% trans "delete query" %}</a>
25
  </li>
26
{% endfor %}
27
</ul>
28
{% else %}
29
<p>{% trans 'No feature queries are defined.' %}</p>
30
{% endif %}
31
<p>
32
<a class="icon-plus button" href="{% url 'opengis-new-featurequery' connector_slug=object.slug %}">{% trans 'New Feature Query' %}</a>
33
</p>
34
</div>
35
</div>
36
{% endif %}
37
{% endblock %}
38

  
passerelle/apps/opengis/urls.py
1
# passerelle - uniform access to multiple data sources and services
2
# Copyright (C) 2017 Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.conf.urls import url
18

  
19
from .views import *
20

  
21
management_urlpatterns = [
22
    url(r'^(?P<connector_slug>[\w,-]+)/queries/new/$',
23
        NewFeatureQueryView.as_view(), name='opengis-new-featurequery'),
24
    url(r'^(?P<connector_slug>[\w,-]+)/queries/(?P<pk>[\w,-]+)/$',
25
        UpdateFeatureQueryView.as_view(), name='opengis-edit-featurequery'),
26
    url(r'^(?P<connector_slug>[\w,-]+)/queries/(?P<pk>[\w,-]+)/delete$',
27
        DeleteFeatureQueryView.as_view(), name='opengis-delete-featurequery'),
28
]
passerelle/apps/opengis/views.py
1
# passerelle - uniform access to multiple data sources and services
2
# Copyright (C) 2017 Entr'ouvert
3
#
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU Affero General Public License as published
6
# by the Free Software Foundation, either version 3 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU Affero General Public License for more details.
13
#
14
# You should have received a copy of the GNU Affero General Public License
15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16

  
17
from django.views.generic import UpdateView, CreateView, DeleteView
18

  
19
from .forms import FeatureQueryForm
20
from .models import OpenGIS, FeatureQuery
21

  
22

  
23
class FeatureQueryView(object):
24
    model = FeatureQuery
25

  
26
    def get_success_url(self):
27
        return self.object.resource.get_absolute_url()
28

  
29
    def get_context_data(self, **kwargs):
30
        ctx = super(FeatureQueryView, self).get_context_data(**kwargs)
31
        ctx['resource'] = OpenGIS.objects.get(slug=self.kwargs['connector_slug'])
32
        return ctx
33

  
34

  
35
class NewFeatureQueryView(FeatureQueryView, CreateView):
36
    form_class = FeatureQueryForm
37
    template_name = 'opengis/featurequery_form.html'
38

  
39
    def get_context_data(self, **kwargs):
40
        ctx = super(NewFeatureQueryView, self).get_context_data(**kwargs)
41
        ctx['resource'] = OpenGIS.objects.get(slug=self.kwargs['connector_slug'])
42
        return ctx
43

  
44
    def get_initial(self):
45
        return {'resource': OpenGIS.objects.get(slug=self.kwargs['connector_slug']).id}
46

  
47

  
48
class UpdateFeatureQueryView(FeatureQueryView, UpdateView):
49
    form_class = FeatureQueryForm
50
    template_name = 'opengis/featurequery_form.html'
51

  
52
    def get_context_data(self, **kwargs):
53
        ctx = super(UpdateFeatureQueryView, self).get_context_data(**kwargs)
54
        ctx['resource'] = OpenGIS.objects.get(slug=self.kwargs['connector_slug'])
55
        return ctx
56

  
57

  
58
class DeleteFeatureQueryView(FeatureQueryView, DeleteView):
59
    pass
0
-