django-gisserver 1.4.1__py3-none-any.whl → 2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_gisserver-1.4.1.dist-info → django_gisserver-2.0.dist-info}/METADATA +23 -13
- django_gisserver-2.0.dist-info/RECORD +66 -0
- {django_gisserver-1.4.1.dist-info → django_gisserver-2.0.dist-info}/WHEEL +1 -1
- gisserver/__init__.py +1 -1
- gisserver/compat.py +23 -0
- gisserver/conf.py +7 -0
- gisserver/db.py +63 -60
- gisserver/exceptions.py +47 -9
- gisserver/extensions/__init__.py +4 -0
- gisserver/{parsers/fes20 → extensions}/functions.py +11 -5
- gisserver/extensions/queries.py +261 -0
- gisserver/features.py +267 -240
- gisserver/geometries.py +34 -39
- gisserver/management/__init__.py +0 -0
- gisserver/management/commands/__init__.py +0 -0
- gisserver/management/commands/loadgeojson.py +291 -0
- gisserver/operations/base.py +129 -305
- gisserver/operations/wfs20.py +428 -336
- gisserver/output/__init__.py +10 -48
- gisserver/output/base.py +198 -143
- gisserver/output/csv.py +81 -85
- gisserver/output/geojson.py +63 -72
- gisserver/output/gml32.py +310 -281
- gisserver/output/iters.py +207 -0
- gisserver/output/results.py +71 -30
- gisserver/output/stored.py +143 -0
- gisserver/output/utils.py +75 -154
- gisserver/output/xmlschema.py +86 -47
- gisserver/parsers/__init__.py +10 -10
- gisserver/parsers/ast.py +320 -0
- gisserver/parsers/fes20/__init__.py +15 -11
- gisserver/parsers/fes20/expressions.py +89 -50
- gisserver/parsers/fes20/filters.py +111 -43
- gisserver/parsers/fes20/identifiers.py +44 -26
- gisserver/parsers/fes20/lookups.py +144 -0
- gisserver/parsers/fes20/operators.py +336 -128
- gisserver/parsers/fes20/sorting.py +107 -34
- gisserver/parsers/gml/__init__.py +12 -11
- gisserver/parsers/gml/base.py +6 -3
- gisserver/parsers/gml/geometries.py +69 -35
- gisserver/parsers/ows/__init__.py +25 -0
- gisserver/parsers/ows/kvp.py +190 -0
- gisserver/parsers/ows/requests.py +158 -0
- gisserver/parsers/query.py +175 -0
- gisserver/parsers/values.py +26 -0
- gisserver/parsers/wfs20/__init__.py +37 -0
- gisserver/parsers/wfs20/adhoc.py +245 -0
- gisserver/parsers/wfs20/base.py +143 -0
- gisserver/parsers/wfs20/projection.py +103 -0
- gisserver/parsers/wfs20/requests.py +482 -0
- gisserver/parsers/wfs20/stored.py +192 -0
- gisserver/parsers/xml.py +249 -0
- gisserver/projection.py +357 -0
- gisserver/static/gisserver/index.css +12 -1
- gisserver/templates/gisserver/index.html +1 -1
- gisserver/templates/gisserver/service_description.html +2 -2
- gisserver/templates/gisserver/wfs/2.0.0/get_capabilities.xml +11 -11
- gisserver/templates/gisserver/wfs/feature_field.html +2 -2
- gisserver/templatetags/gisserver_tags.py +20 -0
- gisserver/types.py +375 -258
- gisserver/views.py +206 -75
- django_gisserver-1.4.1.dist-info/RECORD +0 -53
- gisserver/parsers/base.py +0 -149
- gisserver/parsers/fes20/query.py +0 -275
- gisserver/parsers/tags.py +0 -102
- gisserver/queries/__init__.py +0 -34
- gisserver/queries/adhoc.py +0 -181
- gisserver/queries/base.py +0 -146
- gisserver/queries/stored.py +0 -205
- gisserver/templates/gisserver/wfs/2.0.0/describe_stored_queries.xml +0 -20
- gisserver/templates/gisserver/wfs/2.0.0/list_stored_queries.xml +0 -14
- {django_gisserver-1.4.1.dist-info → django_gisserver-2.0.dist-info}/LICENSE +0 -0
- {django_gisserver-1.4.1.dist-info → django_gisserver-2.0.dist-info}/top_level.txt +0 -0
gisserver/queries/base.py
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from django.db.models import QuerySet
|
|
4
|
-
|
|
5
|
-
from gisserver.exceptions import InvalidParameterValue
|
|
6
|
-
from gisserver.features import FeatureType
|
|
7
|
-
from gisserver.output import FeatureCollection, SimpleFeatureCollection
|
|
8
|
-
from gisserver.parsers import fes20
|
|
9
|
-
from gisserver.types import split_xml_name
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class QueryExpression:
|
|
13
|
-
"""WFS base class for all queries.
|
|
14
|
-
This object type is defined in the WFS spec (as <fes:AbstractQueryExpression>).
|
|
15
|
-
|
|
16
|
-
The subclasses can override the following logic:
|
|
17
|
-
|
|
18
|
-
* :meth:`get_type_names` defines which types this query applies to.
|
|
19
|
-
* :meth:`compile_query` defines how to filter the queryset.
|
|
20
|
-
|
|
21
|
-
For full control, these methods can also be overwritten instead:
|
|
22
|
-
|
|
23
|
-
* :meth:`get_queryset` defines the full results.
|
|
24
|
-
* :meth:`get_hits` to return the collection for RESULTTYPE=hits.
|
|
25
|
-
* :meth:`get_results` to return the collection for RESULTTYPE=results
|
|
26
|
-
"""
|
|
27
|
-
|
|
28
|
-
handle = ""
|
|
29
|
-
value_reference = None
|
|
30
|
-
|
|
31
|
-
def bind(
|
|
32
|
-
self,
|
|
33
|
-
all_feature_types: dict[str, FeatureType],
|
|
34
|
-
value_reference: fes20.ValueReference | None,
|
|
35
|
-
):
|
|
36
|
-
"""Bind the query to presentation-layer logic"""
|
|
37
|
-
self.all_feature_types = all_feature_types
|
|
38
|
-
self.value_reference = value_reference
|
|
39
|
-
|
|
40
|
-
def check_permissions(self, request):
|
|
41
|
-
"""Verify whether the user has access to view these data sources"""
|
|
42
|
-
for feature_type in self.get_type_names():
|
|
43
|
-
feature_type.check_permissions(request)
|
|
44
|
-
|
|
45
|
-
def resolve_type_name(self, type_name, locator="typename") -> FeatureType:
|
|
46
|
-
"""Find the feature type for a given name.
|
|
47
|
-
This is an utility that cusstom subclasses can use.
|
|
48
|
-
"""
|
|
49
|
-
# Strip the namespace prefix. The Python ElementTree parser does
|
|
50
|
-
# not expose the used namespace prefixes, so text-values can't be
|
|
51
|
-
# mapped against it. As we expose just one namespace, just strip it.
|
|
52
|
-
xmlns, type_name = split_xml_name(type_name)
|
|
53
|
-
|
|
54
|
-
try:
|
|
55
|
-
return self.all_feature_types[type_name]
|
|
56
|
-
except KeyError:
|
|
57
|
-
raise InvalidParameterValue(
|
|
58
|
-
locator, f"Typename '{type_name}' doesn't exist in this server."
|
|
59
|
-
) from None
|
|
60
|
-
|
|
61
|
-
def get_hits(self) -> FeatureCollection:
|
|
62
|
-
"""Run the query, return the number of hits only.
|
|
63
|
-
|
|
64
|
-
Override this method in case you need full control over the response data.
|
|
65
|
-
Otherwise, override :meth:`compile_query` or :meth:`get_queryset`.
|
|
66
|
-
"""
|
|
67
|
-
querysets = self.get_querysets()
|
|
68
|
-
return FeatureCollection(
|
|
69
|
-
results=[
|
|
70
|
-
# Include empty feature collections,
|
|
71
|
-
# so the selected feature types are still known.
|
|
72
|
-
SimpleFeatureCollection(feature_type=ft, queryset=qs.none(), start=0, stop=0)
|
|
73
|
-
for ft, qs in querysets
|
|
74
|
-
],
|
|
75
|
-
number_matched=sum(qs.count() for ft, qs in querysets),
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
def get_results(self, start_index=0, count=100) -> FeatureCollection:
|
|
79
|
-
"""Run the query, return the full paginated results.
|
|
80
|
-
|
|
81
|
-
Override this method in case you need full control over the response data.
|
|
82
|
-
Otherwise, override :meth:`compile_query` or :meth:`get_queryset`.
|
|
83
|
-
"""
|
|
84
|
-
stop = start_index + count
|
|
85
|
-
|
|
86
|
-
# The querysets are not executed yet, until the output is reading them.
|
|
87
|
-
querysets = self.get_querysets()
|
|
88
|
-
return FeatureCollection(
|
|
89
|
-
results=[
|
|
90
|
-
SimpleFeatureCollection(feature_type, qs, start=start_index, stop=stop)
|
|
91
|
-
for feature_type, qs in querysets
|
|
92
|
-
]
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
def get_querysets(self) -> list[tuple[FeatureType, QuerySet]]:
|
|
96
|
-
"""Construct the querysets that return the database results."""
|
|
97
|
-
results = []
|
|
98
|
-
for feature_type in self.get_type_names():
|
|
99
|
-
queryset = self.get_queryset(feature_type)
|
|
100
|
-
results.append((feature_type, queryset))
|
|
101
|
-
|
|
102
|
-
return results
|
|
103
|
-
|
|
104
|
-
def get_queryset(self, feature_type: FeatureType) -> QuerySet:
|
|
105
|
-
"""Generate the queryset for the specific feature type.
|
|
106
|
-
|
|
107
|
-
This method can be overwritten in subclasses to define the returned data.
|
|
108
|
-
However, consider overwriting :meth:`compile_query` instead of simple data.
|
|
109
|
-
"""
|
|
110
|
-
queryset = feature_type.get_queryset()
|
|
111
|
-
|
|
112
|
-
# Apply filters
|
|
113
|
-
compiler = self.compile_query(feature_type, using=queryset.db)
|
|
114
|
-
|
|
115
|
-
if self.value_reference is not None:
|
|
116
|
-
if feature_type.resolve_element(self.value_reference.xpath) is None:
|
|
117
|
-
raise InvalidParameterValue(
|
|
118
|
-
"valueReference",
|
|
119
|
-
f"Field '{self.value_reference.xpath}' does not exist.",
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
# For GetPropertyValue, adjust the query so only that value is requested.
|
|
123
|
-
# This makes sure XPath attribute selectors are already handled by the
|
|
124
|
-
# database query, instead of being a presentation-layer handling.
|
|
125
|
-
field = compiler.add_value_reference(self.value_reference)
|
|
126
|
-
queryset = compiler.filter_queryset(queryset, feature_type=feature_type)
|
|
127
|
-
return queryset.values("pk", member=field)
|
|
128
|
-
else:
|
|
129
|
-
return compiler.filter_queryset(queryset, feature_type=feature_type)
|
|
130
|
-
|
|
131
|
-
def get_type_names(self) -> list[FeatureType]:
|
|
132
|
-
"""Tell which type names this query applies to.
|
|
133
|
-
|
|
134
|
-
This method needs to be defined in subclasses.
|
|
135
|
-
"""
|
|
136
|
-
raise NotImplementedError(
|
|
137
|
-
f"{self.__class__.__name__}.get_type_names() should be implemented."
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
def compile_query(self, feature_type: FeatureType, using=None) -> fes20.CompiledQuery:
|
|
141
|
-
"""Define the compiled query that filters the queryset.
|
|
142
|
-
|
|
143
|
-
Subclasses need to define this method, unless
|
|
144
|
-
:meth:`get_queryset` is completely overwritten.
|
|
145
|
-
"""
|
|
146
|
-
raise NotImplementedError()
|
gisserver/queries/stored.py
DELETED
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
"""Handle (stored)query objects.
|
|
2
|
-
|
|
3
|
-
These definitions follow the WFS spec.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
|
|
8
|
-
from dataclasses import dataclass
|
|
9
|
-
|
|
10
|
-
from django.db.models import Q, QuerySet
|
|
11
|
-
|
|
12
|
-
from gisserver.exceptions import InvalidParameterValue, MissingParameterValue, NotFound
|
|
13
|
-
from gisserver.features import FeatureType
|
|
14
|
-
from gisserver.operations.base import Parameter
|
|
15
|
-
from gisserver.output import FeatureCollection
|
|
16
|
-
from gisserver.parsers import fes20
|
|
17
|
-
from gisserver.types import XsdTypes
|
|
18
|
-
|
|
19
|
-
from .base import QueryExpression
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class QueryExpressionText:
|
|
23
|
-
"""Define the body of a stored query.
|
|
24
|
-
|
|
25
|
-
This object type is defined in the WFS spec.
|
|
26
|
-
It may contain a wfs:Query or wfs:StoredQuery element.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
return_feature_types: list[str] | None = None
|
|
30
|
-
language: str = fes20.Filter.query_language
|
|
31
|
-
is_private: bool = False
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@dataclass
|
|
35
|
-
class StoredQueryDescription:
|
|
36
|
-
"""WFS metadata of a stored query.
|
|
37
|
-
This object type is defined in the WFS spec.
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
id: str = None
|
|
41
|
-
title: str | None = None
|
|
42
|
-
abstract: str | None = None
|
|
43
|
-
parameters: dict[str, XsdTypes] | None = None
|
|
44
|
-
expressions: list = None # TODO: support multiple body expressions
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class StoredQuery(QueryExpression):
|
|
48
|
-
"""Base class for stored queries.
|
|
49
|
-
|
|
50
|
-
This represents all predefined queries on the server.
|
|
51
|
-
A good description can be found at:
|
|
52
|
-
https://mapserver.org/ogc/wfs_server.html#stored-queries-wfs-2-0
|
|
53
|
-
|
|
54
|
-
The implementation logic is fully defined by the :class:`QueryExpression`
|
|
55
|
-
base class. For a simple implementation, the following data should be
|
|
56
|
-
overwritten:
|
|
57
|
-
|
|
58
|
-
* :meth:`get_type_names` to define which type this query references.
|
|
59
|
-
* :meth:`compile_query` to define the queryset filter.
|
|
60
|
-
|
|
61
|
-
For advanced overriding, see the :class:`QueryExpression` base class,
|
|
62
|
-
or the :class:`GetFeatureById` implementation.
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
# Official WFS docs have an 'id' and 'parameters' property for the
|
|
66
|
-
# StoredQuery class, but these are avoided here to give subclasses full
|
|
67
|
-
# control over which properties to store. E.g. "id" conflicts with Django
|
|
68
|
-
# model subclasses that stores the query.
|
|
69
|
-
meta: StoredQueryDescription
|
|
70
|
-
|
|
71
|
-
def __init__(self, **parameters):
|
|
72
|
-
self.parameters = parameters
|
|
73
|
-
|
|
74
|
-
@classmethod
|
|
75
|
-
def extract_parameters(cls, KVP) -> dict[str, str]:
|
|
76
|
-
"""Extract the arguments from the key-value-pair (=HTTP GET) request."""
|
|
77
|
-
args = {}
|
|
78
|
-
for name, _xsd_type in cls.meta.parameters.items():
|
|
79
|
-
try:
|
|
80
|
-
args[name] = KVP[name]
|
|
81
|
-
except KeyError:
|
|
82
|
-
raise MissingParameterValue(
|
|
83
|
-
name, f"Stored query {cls.meta.id} requires an '{name}' parameter"
|
|
84
|
-
) from None
|
|
85
|
-
|
|
86
|
-
# Avoid unexpected behavior, check whether the client also sends adhoc query parameters
|
|
87
|
-
for name in ("filter", "bbox", "resourceID"):
|
|
88
|
-
if name not in args and KVP.get(name.upper()):
|
|
89
|
-
raise InvalidParameterValue(
|
|
90
|
-
name, "Stored query can't be combined with adhoc-query parameters"
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
return args
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class StoredQueryRegistry:
|
|
97
|
-
"""Registry of functions to be callable by <fes:Query>."""
|
|
98
|
-
|
|
99
|
-
def __init__(self):
|
|
100
|
-
self.stored_queries = {}
|
|
101
|
-
|
|
102
|
-
def __bool__(self):
|
|
103
|
-
return bool(self.stored_queries)
|
|
104
|
-
|
|
105
|
-
def __iter__(self):
|
|
106
|
-
return iter(self.stored_queries.values())
|
|
107
|
-
|
|
108
|
-
def register(self, meta: StoredQueryDescription | None = None, **meta_kwargs):
|
|
109
|
-
"""Register a custom class that handles a stored query"""
|
|
110
|
-
|
|
111
|
-
def _metadata_dec(query: type[StoredQuery]):
|
|
112
|
-
query.meta = meta or StoredQueryDescription(**meta_kwargs)
|
|
113
|
-
self.stored_queries[query.meta.id] = query
|
|
114
|
-
return query
|
|
115
|
-
|
|
116
|
-
return _metadata_dec
|
|
117
|
-
|
|
118
|
-
def resolve_query(self, query_id) -> type[StoredQuery]:
|
|
119
|
-
"""Find the stored procedure using the ID."""
|
|
120
|
-
try:
|
|
121
|
-
return self.stored_queries[query_id]
|
|
122
|
-
except KeyError:
|
|
123
|
-
raise InvalidParameterValue(
|
|
124
|
-
"STOREDQUERY_ID", f"Stored query does not exist: {query_id}"
|
|
125
|
-
) from None
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
stored_query_registry = StoredQueryRegistry()
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class StoredQueryParameter(Parameter):
|
|
132
|
-
"""Special parameter parsing for the 'STOREDQUERY_ID' parameter"""
|
|
133
|
-
|
|
134
|
-
def __init__(self):
|
|
135
|
-
super().__init__(name="STOREDQUERY_ID", parser=stored_query_registry.resolve_query)
|
|
136
|
-
|
|
137
|
-
def value_from_query(self, KVP: dict):
|
|
138
|
-
"""Customize the request parsing to read custom parameters too."""
|
|
139
|
-
stored_query_class = super().value_from_query(KVP)
|
|
140
|
-
if stored_query_class is None:
|
|
141
|
-
return None
|
|
142
|
-
|
|
143
|
-
parameters = stored_query_class.extract_parameters(KVP)
|
|
144
|
-
return stored_query_class(**parameters)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
@stored_query_registry.register(
|
|
148
|
-
id="urn:ogc:def:query:OGC-WFS::GetFeatureById",
|
|
149
|
-
title="Get feature by identifier",
|
|
150
|
-
abstract="Returns the single feature that corresponds with the ID argument",
|
|
151
|
-
parameters={"ID": XsdTypes.string},
|
|
152
|
-
# expressions=[QueryExpressionText],
|
|
153
|
-
)
|
|
154
|
-
class GetFeatureById(StoredQuery):
|
|
155
|
-
"""The stored query for GetFeatureById.
|
|
156
|
-
|
|
157
|
-
This is essentially the same as:
|
|
158
|
-
|
|
159
|
-
<wfs:Query xmlns:wfs='..." xmlns:fes='...'>
|
|
160
|
-
<fes:Filter><fes:ResourceId rid='{ID}'/></fes:Filter>
|
|
161
|
-
</wfs:Query>
|
|
162
|
-
|
|
163
|
-
Except that the response is supposed to contain only the item itself.
|
|
164
|
-
"""
|
|
165
|
-
|
|
166
|
-
def __init__(self, ID):
|
|
167
|
-
super().__init__(ID=ID)
|
|
168
|
-
try:
|
|
169
|
-
type_name, id = ID.rsplit(".", 1)
|
|
170
|
-
except ValueError:
|
|
171
|
-
# Always report this as 404
|
|
172
|
-
raise NotFound("ID", "Expected typeName.id for ID parameter") from None
|
|
173
|
-
|
|
174
|
-
self.type_name = type_name
|
|
175
|
-
self.id = id
|
|
176
|
-
|
|
177
|
-
def get_type_names(self) -> list[FeatureType]:
|
|
178
|
-
"""Tell which type names this query applies to."""
|
|
179
|
-
feature_type = self.all_feature_types[self.type_name]
|
|
180
|
-
return [feature_type]
|
|
181
|
-
|
|
182
|
-
def get_queryset(self, feature_type: FeatureType) -> QuerySet:
|
|
183
|
-
"""Override to implement ID type checking."""
|
|
184
|
-
try:
|
|
185
|
-
return super().get_queryset(feature_type)
|
|
186
|
-
except (ValueError, TypeError) as e:
|
|
187
|
-
raise InvalidParameterValue("ID", f"Invalid ID value: {e}") from e
|
|
188
|
-
|
|
189
|
-
def get_results(self, *args, **kwargs) -> FeatureCollection:
|
|
190
|
-
"""Override to implement 404 checking."""
|
|
191
|
-
collection = super().get_results(*args, **kwargs)
|
|
192
|
-
|
|
193
|
-
# Directly attempt to collect the data.
|
|
194
|
-
# Avoid having to do that in the output renderer.
|
|
195
|
-
if collection.results[0].first() is None:
|
|
196
|
-
# WFS 2.0.2: Return NotFound instead of InvalidParameterValue
|
|
197
|
-
raise NotFound("ID", f"Feature not found with ID {self.id}.")
|
|
198
|
-
|
|
199
|
-
return collection
|
|
200
|
-
|
|
201
|
-
def compile_query(self, feature_type: FeatureType, using=None) -> fes20.CompiledQuery:
|
|
202
|
-
"""Create the internal query object that will be applied to the queryset."""
|
|
203
|
-
compiler = fes20.CompiledQuery(feature_type=feature_type)
|
|
204
|
-
compiler.add_lookups(Q(pk=self.id), type_name=self.type_name)
|
|
205
|
-
return compiler
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<wfs:DescribeStoredQueriesResponse
|
|
3
|
-
xmlns="http://www.opengis.net/wfs/2.0"
|
|
4
|
-
xmlns:app="{{ app_xml_namespace }}"
|
|
5
|
-
xmlns:wfs="http://www.opengis.net/wfs/2.0"
|
|
6
|
-
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
|
7
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
8
|
-
xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd">
|
|
9
|
-
|
|
10
|
-
{% for query_meta in stored_queries %}
|
|
11
|
-
<StoredQueryDescription id="{{ query_meta.id }}">
|
|
12
|
-
<Title>{{ query_meta.title }}</Title>
|
|
13
|
-
<Abstract>{{ query_meta.abstract }}</Abstract>
|
|
14
|
-
{% for name, type in query_meta.parameters.items %}
|
|
15
|
-
<Parameter name="{{ name }}" type="{{ type.with_prefix }}"/>{% endfor %}
|
|
16
|
-
<QueryExpressionText isPrivate="true" language="urn:ogc:def:queryLanguage:OGC-WFS::WFS_QueryExpression" returnFeatureTypes="{% for feature in feature_types %}{% if not forloop.first %} {% endif %}{{ feature.name }}{% endfor %}"/>
|
|
17
|
-
</StoredQueryDescription>
|
|
18
|
-
{% endfor %}
|
|
19
|
-
|
|
20
|
-
</wfs:DescribeStoredQueriesResponse>
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<wfs:ListStoredQueriesResponse
|
|
3
|
-
xmlns="http://www.opengis.net/wfs/2.0"
|
|
4
|
-
xmlns:app="{{ app_xml_namespace }}"
|
|
5
|
-
xmlns:wfs="http://www.opengis.net/wfs/2.0"
|
|
6
|
-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
7
|
-
xsi:schemaLocation="http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd">
|
|
8
|
-
|
|
9
|
-
<StoredQuery id="urn:ogc:def:query:OGC-WFS::GetFeatureById">
|
|
10
|
-
<Title>Get feature by identifier</Title>{% for feature_type in feature_types %}
|
|
11
|
-
<ReturnFeatureType>{{ feature_type.name }}</ReturnFeatureType>{% endfor %}
|
|
12
|
-
</StoredQuery>
|
|
13
|
-
|
|
14
|
-
</wfs:ListStoredQueriesResponse>
|
|
File without changes
|
|
File without changes
|