diff --git a/lizmap_server/expression_service.py b/lizmap_server/expression_service.py index ed84b5c3..db4d4194 100755 --- a/lizmap_server/expression_service.py +++ b/lizmap_server/expression_service.py @@ -782,6 +782,9 @@ def virtualFields(params: Dict[str, str], response: QgsServerResponse, project: FILTER=An expression to filter layer FIELDS=list of requested field separated by comma WITH_GEOMETRY=False + LIMIT=number of features to return or nothing to return all + SORTING_ORDER=asc or desc, default = asc + SORTING_FIELD=field name to sort by """ logger = Logger() layer_name = params.get('LAYER', '') @@ -865,6 +868,30 @@ def virtualFields(params: Dict[str, str], response: QgsServerResponse, project: req = QgsFeatureRequest() + # set limit + req_limit = params.get('LIMIT', '-1') + try: + req.setLimit(int(req_limit)) + except ValueError: + raise ExpressionServiceError( + "Bad request error", + f"Invalid LIMIT for 'VirtualFields': \"{req_limit}\"", + 400) + + # set orderby + req_sorting_order_param = params.get('SORTING_ORDER', '') + + if req_sorting_order_param in ('asc', 'desc'): + # QGIS expects a boolean to know how to sort + req_sorting_field = params.get('SORTING_FIELD', '') + order_by_clause = QgsFeatureRequest.OrderByClause(req_sorting_field, req_sorting_order_param == 'asc') + req.setOrderBy(QgsFeatureRequest.OrderBy([order_by_clause])) + elif req_sorting_order_param != '' : + raise ExpressionServiceError( + "Bad request error", + f"Invalid SORTING_ORDER for 'VirtualFields': \"{req_sorting_order_param}\"", + 400) + # get filter req_filter = params.get('FILTER', '') if req_filter: diff --git a/test/test_expression_service_virtualfields.py b/test/test_expression_service_virtualfields.py index 8581b8d5..b1605683 100644 --- a/test/test_expression_service_virtualfields.py +++ b/test/test_expression_service_virtualfields.py @@ -1,6 +1,7 @@ import json from urllib.parse import quote +from test.utils import _build_query_string, _check_request __copyright__ = 'Copyright 2019, 3Liz' __license__ = 'GPL version 3' @@ -204,3 +205,88 @@ def test_request_with_filter_fields_geometry(client): assert b['features'][0]['properties']['a'] == 1 assert 'b' in b['features'][0]['properties'] assert b['features'][0]['properties']['b'] == 2 + +def test_request_limit(client): + """ Test Expression VirtualFields request + """ + projectfile = "france_parts.qgs" + + # Make a request + qs = { + "SERVICE": "EXPRESSION", + "REQUEST": "VirtualFields", + "MAP": "france_parts.qgs", + "LAYER": "france_parts", + "VIRTUALS": "{\"a\":\"%s\", \"b\":\"%s\"}" % ( + quote('1', safe=''), quote('1 + 1', safe='')), + "LIMIT": "2", + } + + rv = client.get(_build_query_string(qs), projectfile) + b = _check_request(rv, http_code=200) + + assert 'type' in b + assert b['type'] == 'FeatureCollection' + + assert 'features' in b + assert len(b['features']) == 2 + + assert 'type' in b['features'][0] + assert b['features'][0]['type'] == 'Feature' + + assert 'geometry' in b['features'][0] + assert b['features'][0]['geometry'] is None + + assert 'properties' in b['features'][0] + assert 'NAME_1' in b['features'][0]['properties'] + assert 'Region' in b['features'][0]['properties'] + + assert 'a' in b['features'][0]['properties'] + assert b['features'][0]['properties']['a'] == 1 + assert 'b' in b['features'][0]['properties'] + assert b['features'][0]['properties']['b'] == 2 + + +def test_request_order(client): + """ Test Expression VirtualFields request + """ + projectfile = "france_parts.qgs" + + # Make a request + qs = { + "SERVICE": "EXPRESSION", + "REQUEST": "VirtualFields", + "MAP": "france_parts.qgs", + "LAYER": "france_parts", + "VIRTUALS": "{\"a\":\"%s\", \"b\":\"%s\"}" % ( + quote('1', safe=''), quote('1 + 1', safe='')), + "SORTING_ORDER": "desc", + "SORTING_FIELD": "NAME_1", + } + + rv = client.get(_build_query_string(qs), projectfile) + b = _check_request(rv, http_code=200) + + assert 'type' in b + assert b['type'] == 'FeatureCollection' + + assert 'features' in b + assert len(b['features']) == 4 + + assert 'type' in b['features'][0] + assert b['features'][0]['type'] == 'Feature' + + assert 'geometry' in b['features'][0] + assert b['features'][0]['geometry'] is None + + assert 'properties' in b['features'][0] + assert 'NAME_1' in b['features'][0]['properties'] + assert 'Region' in b['features'][0]['properties'] + + assert 'a' in b['features'][0]['properties'] + assert b['features'][0]['properties']['a'] == 1 + assert 'b' in b['features'][0]['properties'] + assert b['features'][0]['properties']['b'] == 2 + + assert b['features'][0]['id'] == 'france_parts.2' + assert b['features'][3]['id'] == 'france_parts.0'