From 1344fe6b465ec3b6fda009535945ef0a22f91fee Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 27 Feb 2025 09:51:11 +0100 Subject: [PATCH] feat: basic filtering by tags --- docs/config/settings.md | 5 ++++- umap/context_processors.py | 1 + umap/templates/umap/search_bar.html | 12 ++++++++++-- umap/tests/test_views.py | 24 ++++++++++++++++++++++++ umap/views.py | 8 +++++++- 5 files changed, 46 insertions(+), 4 deletions(-) diff --git a/docs/config/settings.md b/docs/config/settings.md index 5211f7b5..c6b103f6 100644 --- a/docs/config/settings.md +++ b/docs/config/settings.md @@ -323,7 +323,10 @@ CREATE EXTENSION btree_gin; ALTER TEXT SEARCH CONFIGURATION umapdict ALTER MAPPING FOR hword, hword_part, word WITH unaccent, simple; # Now create the index -CREATE INDEX IF NOT EXISTS search_idx ON umap_map USING GIN(to_tsvector('umapdict', COALESCE(name, ''::character varying)::text), share_status); +CREATE INDEX IF NOT EXISTS search_idx ON umap_map USING GIN(to_tsvector('umapdict', COALESCE(name, ''::character varying)::text), share_status, tags); + +# You should also create an index for tag filtering: +CREATE INDEX IF NOT EXISTS tags_idx ON umap_map USING GIN(share_status, tags); ``` Then set: diff --git a/umap/context_processors.py b/umap/context_processors.py index fcabcfb4..6064a152 100644 --- a/umap/context_processors.py +++ b/umap/context_processors.py @@ -14,6 +14,7 @@ def settings(request): "UMAP_DEMO_SITE": djsettings.UMAP_DEMO_SITE, "UMAP_HOST_INFOS": djsettings.UMAP_HOST_INFOS, "UMAP_ALLOW_EDIT_PROFILE": djsettings.UMAP_ALLOW_EDIT_PROFILE, + "UMAP_TAGS": djsettings.UMAP_TAGS, } diff --git a/umap/templates/umap/search_bar.html b/umap/templates/umap/search_bar.html index 701a0fb0..c3f22b0e 100644 --- a/umap/templates/umap/search_bar.html +++ b/umap/templates/umap/search_bar.html @@ -5,14 +5,22 @@
-
+
-
+
+ +
+
diff --git a/umap/tests/test_views.py b/umap/tests/test_views.py index 81ef0cc2..e13a9c9a 100644 --- a/umap/tests/test_views.py +++ b/umap/tests/test_views.py @@ -486,3 +486,27 @@ def test_cannot_search_deleted_map(client, map): url = reverse("search") response = client.get(url + "?q=Blé") assert "Blé dur" not in response.content.decode() + + +@pytest.mark.django_db +def test_filter_by_tag(client, map): + # Very basic search, that do not deal with accent nor case. + # See install.md for how to have a smarter dict + index. + map.name = "Blé dur" + map.tags = ["bike"] + map.save() + url = reverse("search") + response = client.get(url + "?tags=bike") + assert "Blé dur" in response.content.decode() + + +@pytest.mark.django_db +def test_can_combine_search_and_filter(client, map): + # Very basic search, that do not deal with accent nor case. + # See install.md for how to have a smarter dict + index. + map.name = "Blé dur" + map.tags = ["bike"] + map.save() + url = reverse("search") + response = client.get(url + "?q=dur&tags=bike") + assert "Blé dur" in response.content.decode() diff --git a/umap/views.py b/umap/views.py index 0d05a75c..aed882bf 100644 --- a/umap/views.py +++ b/umap/views.py @@ -334,12 +334,18 @@ class TeamMaps(PaginatorMixin, DetailView): class SearchMixin: def get_search_queryset(self, **kwargs): q = self.request.GET.get("q") + tags = [t for t in self.request.GET.getlist("tags") if t] + qs = Map.objects.all() if q: vector = SearchVector("name", config=settings.UMAP_SEARCH_CONFIGURATION) query = SearchQuery( q, config=settings.UMAP_SEARCH_CONFIGURATION, search_type="websearch" ) - return Map.objects.annotate(search=vector).filter(search=query) + qs = qs.annotate(search=vector).filter(search=query) + if tags: + qs = qs.filter(tags__contains=tags) + if q or tags: + return qs class Search(PaginatorMixin, TemplateView, PublicMapsMixin, SearchMixin):