Skip to content

Commit

Permalink
Check for 'field', 'suggest' and 'ordering' API parameters in HTTP PO…
Browse files Browse the repository at this point in the history
…ST calls. (#748) (#750)

Co-authored-by: wlorenzetti <lorenzett@gis3w.it>
(cherry picked from commit b94e09b)
  • Loading branch information
wlorenzetti authored Feb 12, 2024
1 parent e28c17f commit 02cee91
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 7 deletions.
27 changes: 23 additions & 4 deletions g3w-admin/core/api/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,18 @@ def apply_filter(self, request, metadata_layer, qgis_feature_request, view):

qgis_layer = metadata_layer.qgis_layer

if request.query_params.get('search'):
# Try to get param from GET
search_value = request.query_params.get('search')

if not search_value:
# Try to get from POST
search_value = request.data.get('search')

if search_value:

search_parts = []

for search_term in request.query_params.get('search').split(','):
for search_term in search_value.split(','):

search_term = self._quote_value('%' + search_term + '%')
exp_template = '{field_name} ILIKE ' + search_term
Expand Down Expand Up @@ -114,11 +121,18 @@ def apply_filter(self, request, metadata_layer, qgis_feature_request, view):

qgis_layer = metadata_layer.qgis_layer

if request.query_params.get('ordering') is not None:
# Try to get param from GET
ordering_value = request.query_params.get('ordering')

if not ordering_value:
# Try to get from POST
ordering_value = request.data.get('ordering')

if ordering_value is not None:

ordering_rules = []

for ordering in request.query_params.get('ordering').split(','):
for ordering in ordering_value.split(','):
ascending = True
if ordering.startswith('-'):
ordering = ordering[1:]
Expand Down Expand Up @@ -215,8 +229,13 @@ def apply_filter(self, request, metadata_layer, qgis_feature_request, view):

qgis_layer = metadata_layer.qgis_layer

# Try to get param from GET
suggest_value = request.query_params.get('suggest')

if not suggest_value:
# Try to get from POST
suggest_value = request.data.get('suggest')

if suggest_value:

# get field and value
Expand Down
95 changes: 92 additions & 3 deletions g3w-admin/qdjango/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -651,11 +651,11 @@ def tearDownClass(cls):
cls.project322.instance.delete()
super().tearDownClass()

def _testApiCall(self, view_name, args, kwargs={}, status_auth=200, login=True, logout=True):
def _testApiCall(self, view_name, args, kwargs={}, status_auth=200, login=True, logout=True, method='get'):
"""Utility to make test calls for admin01 user"""

path = reverse(view_name, args=args)
if kwargs:
if kwargs and method == 'get':
path += '?'
parts = []
for k, v in kwargs.items():
Expand All @@ -671,7 +671,8 @@ def _testApiCall(self, view_name, args, kwargs={}, status_auth=200, login=True,
if login:
self.assertTrue(self.client.login(
username='admin01', password='admin01'))
response = self.client.get(path)

response = getattr(self.client, method)(path, data=kwargs)
self.assertEqual(response.status_code, status_auth)
if logout:
self.client.logout()
Expand Down Expand Up @@ -1304,6 +1305,7 @@ def test_server_filters_combination_api(self):
qgs_request.setFilterExpression('"ISO2_CODE" = \'IT\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1313,6 +1315,17 @@ def test_server_filters_combination_api(self):

self.assertEqual(resp['vector']['count'], total_count)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'field': 'ISO2_CODE|eq|IT'
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)

qgs_request = QgsFeatureRequest()
qgs_request.setFilterExpression(
'"ISO2_CODE" = \'IT\' OR "ISO2_CODE" = \'FR\'')
Expand All @@ -1332,6 +1345,7 @@ def test_server_filters_combination_api(self):
'"ISO2_CODE" = \'IT\' AND "POPULATION" > 10000 OR "ISO2_CODE" = \'FR\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1341,6 +1355,17 @@ def test_server_filters_combination_api(self):

self.assertEqual(resp['vector']['count'], total_count)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'field': 'ISO2_CODE|eq|IT|AND,POPULATION|gt|10000|OR,ISO2_CODE|eq|FR',
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)

qgs_request = QgsFeatureRequest()
qgs_request.setFilterExpression('"NAME" LIKE \'%Flo%\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])
Expand All @@ -1358,6 +1383,7 @@ def test_server_filters_combination_api(self):
qgs_request.setFilterExpression('"NAME" ILIKE \'%flo%\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1367,11 +1393,23 @@ def test_server_filters_combination_api(self):

self.assertEqual(resp['vector']['count'], total_count)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'field': 'NAME|ilike|flo'
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)

qgs_request = QgsFeatureRequest()
qgs_request.setFilterExpression(
'"ISO2_CODE" = \'IT\' AND "NAME" = \'Florence\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1381,12 +1419,24 @@ def test_server_filters_combination_api(self):

self.assertEqual(resp['vector']['count'], total_count)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'field': 'ISO2_CODE|eq|IT,NAME|eq|Florence'
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)

# check SuggestFilterBackend
# --------------------------
qgs_request = QgsFeatureRequest()
qgs_request.setFilterExpression('"NAME" ILIKE \'%flo%\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1396,13 +1446,25 @@ def test_server_filters_combination_api(self):

self.assertEqual(resp['vector']['count'], total_count)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'suggest': 'NAME|flo'
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)

# check SuggestFilterBackend + FieldFilterBackend
# -----------------------------------------------
qgs_request = QgsFeatureRequest()
qgs_request.setFilterExpression(
'"NAME" ILIKE \'%flo%\' AND "ISO2_CODE" = \'IT\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1414,11 +1476,25 @@ def test_server_filters_combination_api(self):
self.assertEqual(resp['vector']['count'], total_count)
self.assertEqual(resp['vector']['count'], 2)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'suggest': 'NAME|flo',
'field': 'ISO2_CODE|eq|IT'
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)
self.assertEqual(resp['vector']['count'], 2)

qgs_request = QgsFeatureRequest()
qgs_request.setFilterExpression(
'"NAME" ILIKE \'%flo%\' AND "ISO2_CODE" = \'IT\' AND "NAME" = \'Florence\'')
total_count = len([f for f in qgis_layer.getFeatures(qgs_request)])

# Test http 'get' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
Expand All @@ -1430,6 +1506,19 @@ def test_server_filters_combination_api(self):
self.assertEqual(resp['vector']['count'], total_count)
self.assertEqual(resp['vector']['count'], 1)

# Test http 'post' method:
resp = json.loads(self._testApiCall('core-vector-api',
['data', 'qdjango', self.project310.instance.pk,
cities.qgs_layer_id],
{
'suggest': 'NAME|flo',
'field': 'ISO2_CODE|eq|IT,NAME|eq|Florence'
},
method='post').content)

self.assertEqual(resp['vector']['count'], total_count)
self.assertEqual(resp['vector']['count'], 1)

def test_unique_request_api_param(self):
""" Test 'unique' url request param for 'data' vector API """

Expand Down

0 comments on commit 02cee91

Please sign in to comment.