From fad346feabf841eab67b4912abafc0d2cf8bc3f3 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: May 04 2018 09:11:57 +0000 Subject: Add 'order_by' query key which can be used to order composes in REST API response. --- diff --git a/server/odcs/server/api_utils.py b/server/odcs/server/api_utils.py index b34e394..072f7aa 100644 --- a/server/odcs/server/api_utils.py +++ b/server/odcs/server/api_utils.py @@ -228,6 +228,35 @@ def pagination_metadata(p_query, request_args): return pagination_data +def _order_by(flask_request, query, base_class, allowed_keys, default_key): + """ + Parses the "order_by" argument from flask_request.args, checks that + it is allowed for ordering in `allowed_keys` list and sets the ordering + in the `query`. + In case "order_by" is not set in flask_request.args, use `default_key` + instead. + + If "order_by" argument starts with minus sign ('-'), the descending order + is used. + """ + order_by = flask_request.args.get('order_by', default_key, type=str) + if order_by and len(order_by) > 1 and order_by[0] == "-": + order_asc = False + order_by = order_by[1:] + else: + order_asc = True + + if order_by not in allowed_keys: + raise ValueError( + 'An invalid order_by key was suplied, allowed keys are: ' + '%r' % allowed_keys) + + order_by_attr = getattr(base_class, order_by) + if not order_asc: + order_by_attr = order_by_attr.desc() + return query.order_by(order_by_attr) + + def filter_composes(flask_request): """ Returns a flask_sqlalchemy.Pagination object based on the request parameters @@ -245,6 +274,11 @@ def filter_composes(flask_request): if search_query: query = query.filter_by(**search_query) + query = _order_by(flask_request, query, Compose, + ["id", "owner", "source_Type", "koji_event", + "state", "time_to_expire", "time_submitted", + "time_done", "time_removed"], "-id") + page = flask_request.args.get('page', 1, type=int) per_page = flask_request.args.get('per_page', 10, type=int) return query.paginate(page, per_page, False) diff --git a/server/tests/test_views.py b/server/tests/test_views.py index 98afe9b..58820bd 100644 --- a/server/tests/test_views.py +++ b/server/tests/test_views.py @@ -611,6 +611,29 @@ class TestViews(ViewBaseTest): evs = json.loads(resp.get_data(as_text=True))['items'] self.assertEqual(len(evs), 1) + def test_query_composes_order_by_default(self): + resp = self.client.get('/api/1/composes/') + composes = json.loads(resp.get_data(as_text=True))['items'] + self.assertEqual([2, 1], [compose["id"] for compose in composes]) + + def test_query_composes_order_by_id_asc(self): + resp = self.client.get('/api/1/composes/?order_by=id') + composes = json.loads(resp.get_data(as_text=True))['items'] + self.assertEqual([1, 2], [compose["id"] for compose in composes]) + + def test_query_composes_order_by_id_desc(self): + resp = self.client.get('/api/1/composes/?order_by=-id') + composes = json.loads(resp.get_data(as_text=True))['items'] + self.assertEqual([2, 1], [compose["id"] for compose in composes]) + + def test_query_composes_order_by_id_unknown_key(self): + resp = self.client.get('/api/1/composes/?order_by=foo') + data = json.loads(resp.get_data(as_text=True)) + self.assertEqual(data['status'], 400) + self.assertEqual(data['error'], 'Bad Request') + self.assertTrue(data['message'].startswith( + "An invalid order_by key was suplied, allowed keys are")) + def test_delete_compose(self): with freeze_time(self.initial_datetime) as frozen_datetime: c3 = Compose.create(