From be9bc8b5cc1168d94b5cc539b87bdf97eb718c14 Mon Sep 17 00:00:00 2001 From: Michael Weimann Date: Sun, 16 Jan 2022 16:35:23 +0100 Subject: [PATCH] add pagination --- ki/actions/seed.py | 2 ++ ki/handlers/find_profiles.py | 20 +++++++++++------ ki/test/test_find_profiles_endpoint.py | 30 ++++++++++++++++---------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/ki/actions/seed.py b/ki/actions/seed.py index 17fede2..2ccf157 100644 --- a/ki/actions/seed.py +++ b/ki/actions/seed.py @@ -143,6 +143,8 @@ def seed(dev: bool): db.session.add(peter_fr) seed_user("klaus") + for i in range(1, 20): + seed_user(f"babsi{i}", visible=True) seed_user("dirtydieter", visible=True, diff --git a/ki/handlers/find_profiles.py b/ki/handlers/find_profiles.py index 1a1b007..1f11967 100644 --- a/ki/handlers/find_profiles.py +++ b/ki/handlers/find_profiles.py @@ -8,7 +8,10 @@ from ki.models import Profile, ProfileSkill, Skill, ProfileLanguage, Language def find_profiles(): - page = int(request.args.get("page", 1)) + try: + page = int(request.args.get("page", 1)) + except ValueError: + page = 1 if page < 1: return make_response({"messages": {"page": "Die angefragte Seite muss mindestens 1 sein"}}, 400) @@ -19,6 +22,7 @@ def find_profiles(): return make_response({"messages": {"page_size": "Die maximale Anzahl Einträge pro Seite beträgt 100"}}, 400) query = Profile.query.distinct(Profile.id) \ + .order_by(Profile.nickname) \ .filter(Profile.visible.is_(True)) \ .join(Profile.skills, isouter=True).join(ProfileSkill.skill, isouter=True) \ .join(Profile.languages, isouter=True).join(ProfileLanguage.language, isouter=True) @@ -33,13 +37,15 @@ def find_profiles(): nickname = request.args.get("nickname") query = query.filter(Profile.nickname.like(f"%{nickname}%")) - count = query.count() - - offset = (page - 1) * page_size - db_profiles = query.limit(page_size).offset(offset).all() + paginated_result = query.paginate(page=page, per_page=page_size) api_profiles = [] - for db_profile in db_profiles: + for db_profile in paginated_result.items: api_profiles.append(db_profile.to_dict()) - return make_response({"total": count, "profiles": api_profiles}) + return make_response({ + "total": paginated_result.total, + "pages": paginated_result.pages, + "page": paginated_result.page, + "profiles": api_profiles + }) diff --git a/ki/test/test_find_profiles_endpoint.py b/ki/test/test_find_profiles_endpoint.py index a87181d..0146721 100644 --- a/ki/test/test_find_profiles_endpoint.py +++ b/ki/test/test_find_profiles_endpoint.py @@ -20,25 +20,33 @@ class TestFindProfilesEndpoint(ApiTest): response = self.client.get("/users/profiles?nickname=horsthorsthorst", headers={"Authorization": "Bearer " + token}) self.assertEqual(response.status_code, 200) - self.assertEqual(response.json, {"total": 0, "profiles": []}) + self.assertEqual(response.json, {"total": 0, "page": 1, "pages": 0, "profiles": []}) def test_find_sql_specialchars(self): token = self.login("peter", "geheim")["token"] response = self.client.get("/users/profiles?nickname=%22%27%25", headers={"Authorization": "Bearer " + token}) self.assertEqual(response.status_code, 200) - self.assertEqual(response.json, {"total": 0, "profiles": []}) + self.assertEqual(response.json, {"total": 0, "page": 1, "pages": 0, "profiles": []}) - def test_find_all(self): + def test_find_all_page1(self): token = self.login("peter", "geheim")["token"] response = self.client.get("/users/profiles", headers={"Authorization": "Bearer " + token}) self.assertEqual(response.status_code, 200) - self.assertDictContainsSubset({"total": 4}, response.json) - self.assertDictContainsSubset({"nickname": "dirtydieter"}, response.json["profiles"][0]) + self.assertDictContainsSubset({"total": 23, "page": 1, "pages": 2}, response.json) + self.assertDictContainsSubset({"nickname": "babsi1"}, response.json["profiles"][0]) + self.assertDictContainsSubset({"nickname": "dirtydieter"}, response.json["profiles"][19]) + + def test_find_all_page2(self): + token = self.login("peter", "geheim")["token"] + + response = self.client.get("/users/profiles?page=2", headers={"Authorization": "Bearer " + token}) + self.assertEqual(response.status_code, 200) + self.assertDictContainsSubset({"total": 23, "page": 2, "pages": 2}, response.json) + self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][0]) self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][1]) - self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][2]) - self.assertDictContainsSubset({"nickname": "monique"}, response.json["profiles"][3]) + self.assertDictContainsSubset({"nickname": "monique"}, response.json["profiles"][2]) def test_find_dieter(self): token = self.login("peter", "geheim")["token"] @@ -62,8 +70,8 @@ class TestFindProfilesEndpoint(ApiTest): response = self.client.get("/users/profiles?search=sql", headers={"Authorization": "Bearer " + token}) self.assertEqual(response.status_code, 200) self.assertDictContainsSubset({"total": 2}, response.json) - self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][0]) - self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][1]) + self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][0]) + self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][1]) def test_find_postgres(self): token = self.login("peter", "geheim")["token"] @@ -71,8 +79,8 @@ class TestFindProfilesEndpoint(ApiTest): response = self.client.get("/users/profiles?search=post", headers={"Authorization": "Bearer " + token}) self.assertEqual(response.status_code, 200) self.assertDictContainsSubset({"total": 2}, response.json) - self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][0]) - self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][1]) + self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][0]) + self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][1]) def test_find_php_franzosen(self): token = self.login("peter", "geheim")["token"]