From b8c2644086ba95f1245de2a938e9020f0fabafd2 Mon Sep 17 00:00:00 2001 From: Michael Weimann Date: Mon, 16 Aug 2021 22:41:03 +0200 Subject: [PATCH] implement generic search closes #47 --- ki/actions/seed.py | 55 ++++++++++++++++++-------- ki/handlers/find_profiles.py | 14 +++++-- ki/models.py | 7 ++++ ki/test/test_find_profiles_endpoint.py | 50 +++++++++++++++++++++++ 4 files changed, 107 insertions(+), 19 deletions(-) diff --git a/ki/actions/seed.py b/ki/actions/seed.py index b3b1a01..5140ea3 100644 --- a/ki/actions/seed.py +++ b/ki/actions/seed.py @@ -26,6 +26,31 @@ def seed_contacttypes(): db.session.add(ContactType(id=int(contacttype["id"]), name=contacttype["name"])) +def seed_user(nickname, visible=False, skills=[], languages=[], volunteerwork="", availability="", freetext=""): + app.logger.info(f"seeding {nickname} \\o/") + + user = User(auth_id=nickname) + db.session.add(user) + + profile = Profile(nickname=nickname, + pronouns="", + volunteerwork=volunteerwork, + availability=availability, + freetext=freetext, + visible=visible, + user=user) + + for skill_data in skills: + skill = ProfileSkill(profile=profile, skill_id=skill_data[0], level=skill_data[1]) + db.session.add(skill) + + for language_data in languages: + language = ProfileLanguage(profile=profile, language_id=language_data[0], level=language_data[1]) + db.session.add(language) + + db.session.add(profile) + + def seed(dev: bool): seed_contacttypes() @@ -105,23 +130,21 @@ def seed(dev: bool): peter_fr = ProfileLanguage(profile=peters_profile, language_id="fr", level=3) db.session.add(peter_fr) - app.logger.info("seeding klaus :D") + seed_user("klaus") - klaus = User(auth_id="klaus") - db.session.add(klaus) + seed_user("dirtydieter", + visible=True, + volunteerwork="Müll sammeln", + availability="Nur nachts", + freetext="1001010010111!!!", + skills=[(Skill.skill_id_php, 5)]) - app.logger.info("seeding dieter \\o/") - - dieter = User(auth_id="dieter") - db.session.add(dieter) - - dieters_profile = Profile(nickname="dirtydieter", - pronouns="", - volunteerwork="Müll sammeln", - availability="Nur nachts", - freetext="1001010010111!!!", - visible=True, - user=dieter) - db.session.add(dieters_profile) + seed_user("jutta", + visible=True, + languages=[("fr", 5)], + skills=[(Skill.skill_id_php, 3), (Skill.skill_id_mysql, 4)]) + seed_user("giesela", visible=True, skills=[(Skill.skill_id_mysql, 3), (Skill.skill_id_postgresql, 5)]) + seed_user("bertha", visible=False, skills=[(Skill.skill_id_sqlite, 3), (Skill.skill_id_postgresql, 5)]) + seed_user("monique", visible=True, languages=[("fr", 4)]) db.session.commit() diff --git a/ki/handlers/find_profiles.py b/ki/handlers/find_profiles.py index caac477..a4063bf 100644 --- a/ki/handlers/find_profiles.py +++ b/ki/handlers/find_profiles.py @@ -4,7 +4,7 @@ from flask import make_response, request -from ki.models import Profile +from ki.models import Profile, ProfileSkill, Skill, ProfileLanguage, Language def find_profiles(): @@ -18,13 +18,21 @@ def find_profiles(): if page_size > 100: return make_response({"messages": {"page_size": "Die maximale Anzahl Einträge pro Seite beträgt 100"}}, 400) - query = Profile.query.filter(Profile.visible.is_(True)) + query = Profile.query.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) + + if "search" in request.args: + terms = request.args["search"].split(" ") + for term in terms: + query = query.filter( + Profile.nickname.like(f"%{term}%") | Skill.name.like(f"%{term}%") | Language.name.like(f"%{term}%")) if "nickname" in request.args: nickname = request.args.get("nickname") query = query.filter(Profile.nickname.like(f"%{nickname}%")) - count = query.count() + count = query.distinct(Profile.id).count() offset = (page - 1) * page_size db_profiles = query.limit(page_size).offset(offset).all() diff --git a/ki/models.py b/ki/models.py index 64c5b44..af0ee5f 100644 --- a/ki/models.py +++ b/ki/models.py @@ -133,6 +133,13 @@ class Address(db.Model): class Skill(db.Model): + skill_id_php = 1 + skill_id_python = 3 + skill_id_sqlalchemy = 7 + skill_id_mysql = 9 + skill_id_postgresql = 10 + skill_id_sqlite = 11 + __tablename__ = "skill" id = Column(Integer, primary_key=True) diff --git a/ki/test/test_find_profiles_endpoint.py b/ki/test/test_find_profiles_endpoint.py index 7c45c45..aad5c78 100644 --- a/ki/test/test_find_profiles_endpoint.py +++ b/ki/test/test_find_profiles_endpoint.py @@ -34,9 +34,59 @@ class TestFindProfilesEndpoint(ApiTest): 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]) + + def test_find_dieter(self): + token = self.login("peter", "geheim")["token"] + + response = self.client.get("/users/profiles?search=dieter%20php", headers={"Authorization": "Bearer " + token}) + self.assertEqual(response.status_code, 200) self.assertDictContainsSubset({"total": 1}, response.json) self.assertDictContainsSubset({"nickname": "dirtydieter"}, response.json["profiles"][0]) + def test_not_find_dieter(self): + token = self.login("peter", "geheim")["token"] + + response = self.client.get("/users/profiles?search=dieter%20sqlite", + headers={"Authorization": "Bearer " + token}) + self.assertEqual(response.status_code, 200) + self.assertDictContainsSubset({"total": 0}, response.json) + + def test_find_sql(self): + token = self.login("peter", "geheim")["token"] + + 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]) + + def test_find_postgres(self): + token = self.login("peter", "geheim")["token"] + + response = self.client.get("/users/profiles?search=post", headers={"Authorization": "Bearer " + token}) + self.assertEqual(response.status_code, 200) + self.assertDictContainsSubset({"total": 1}, response.json) + self.assertDictContainsSubset({"nickname": "giesela"}, response.json["profiles"][0]) + + def test_find_php_franzosen(self): + token = self.login("peter", "geheim")["token"] + + response = self.client.get("/users/profiles?search=php%20franz", headers={"Authorization": "Bearer " + token}) + self.assertEqual(response.status_code, 200) + self.assertDictContainsSubset({"total": 1}, response.json) + self.assertDictContainsSubset({"nickname": "jutta"}, response.json["profiles"][0]) + + def test_find_franzosen(self): + token = self.login("peter", "geheim")["token"] + + response = self.client.get("/users/profiles?search=französisch", 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": "monique"}, response.json["profiles"][1]) + if __name__ == "main": unittest.main()