From caebde3f3b4e3541eed6fe98e7d178e3c5434b82 Mon Sep 17 00:00:00 2001 From: mattiagiupponi <51856725+mattiagiupponi@users.noreply.github.com> Date: Wed, 10 Mar 2021 14:33:22 +0100 Subject: [PATCH] [Backport to 3.2.x][Fixes: #6925] Thesauri improvements (#7055) * [Fixes: #7033] Mandatory fields in editor * [Fixes #6925] Add new thesaurus behaviour for documents and maps * [Fixes #6925] Facet endpoint changed to serve default label if translated one does not exists * [Fixes #6925] Facet endpoint changed to serve default label if translated one does not exists --- geonode/api/api.py | 34 +++++--- geonode/api/tests.py | 79 +++++++++++++++++++ .../templates/search/_t_keywords_filter.html | 2 +- 3 files changed, 101 insertions(+), 14 deletions(-) diff --git a/geonode/api/api.py b/geonode/api/api.py index e5f1e3b7b3d..18204aa57e2 100644 --- a/geonode/api/api.py +++ b/geonode/api/api.py @@ -41,7 +41,7 @@ from guardian.shortcuts import get_objects_for_user from tastypie.bundle import Bundle -from geonode.base.models import ResourceBase +from geonode.base.models import ResourceBase, ThesaurusKeyword from geonode.base.models import TopicCategory from geonode.base.models import Region from geonode.base.models import HierarchicalKeyword @@ -201,12 +201,10 @@ def build_filters(self, filters={}, ignore_bad_filters=False): orm_filters = super(ThesaurusKeywordResource, self).build_filters(_filters) if id is not None: - orm_filters['keyword__id'] = id - - orm_filters['lang'] = _filters['lang'] if 'lang' in _filters else get_language() + orm_filters['id__in'] = id if 'thesaurus' in _filters: - orm_filters['keyword__thesaurus__identifier'] = _filters['thesaurus'] + orm_filters['thesaurus__identifier'] = _filters['thesaurus'] return orm_filters @@ -216,27 +214,37 @@ def serialize(self, request, data, format, options={}): return super(ThesaurusKeywordResource, self).serialize(request, data, format, options) def dehydrate_id(self, bundle): - return bundle.obj.keyword.id + return bundle.obj.id def dehydrate_label_id(self, bundle): return bundle.obj.id def dehydrate_thesaurus_identifier(self, bundle): - return bundle.obj.keyword.thesaurus.identifier + return bundle.obj.thesaurus.identifier + + def dehydrate(self, bundle): + lang = get_language() + label = ThesaurusKeywordLabel.objects.filter(keyword=bundle.data['id']).filter(lang=lang) + if label.exists(): + bundle.data['label_id'] = label.get().id + bundle.data['label'] = label.get().label + bundle.data['alt_label'] = label.get().label + else: + bundle.data['label'] = bundle.data['alt_label'] + + return bundle class Meta: - queryset = ThesaurusKeywordLabel.objects \ + queryset = ThesaurusKeyword.objects \ .all() \ - .order_by('label') \ - .select_related('keyword') \ - .select_related('keyword__thesaurus') + .order_by('alt_label') \ + .select_related('thesaurus') resource_name = 'thesaurus/keywords' allowed_methods = ['get'] filtering = { 'id': ALL, - 'label': ALL, - 'lang': ALL, + 'alt_label': ALL, 'thesaurus': ALL, } serializer = CountJSONSerializer() diff --git a/geonode/api/tests.py b/geonode/api/tests.py index 30ab74f2153..921da3081cf 100644 --- a/geonode/api/tests.py +++ b/geonode/api/tests.py @@ -17,6 +17,8 @@ # along with this program. If not, see . # ######################################################################### +from unittest.case import TestCase +from unittest.mock import patch from django.conf import settings from datetime import datetime, timedelta @@ -526,3 +528,80 @@ def test_tags_lockdown(self): resp = self.api_client.get(filter_url) self.assertValidJSONResponse(resp) self.assertEqual(len(self.deserialize(resp)['objects']), 5) + + +class ThesaurusKeywordResourceTests(ResourceTestCaseMixin, TestCase): + # loading test thesausurs + fixtures = ["test_thesaurus.json"] + + def setUp(self): + super(ThesaurusKeywordResourceTests, self).setUp() + + self.list_url = reverse("api_dispatch_list", kwargs={"api_name": "api", "resource_name": "thesaurus/keywords"}) + + def test_api_will_return_a_valid_json_response(self): + resp = self.api_client.get(self.list_url) + self.assertValidJSONResponse(resp) + + def test_will_return_empty_if_the_thesaurus_does_not_exists(self): + url = f"{self.list_url}?thesaurus=invalid-identifier" + resp = self.api_client.get(url) + self.assertValidJSONResponse(resp) + self.assertEqual(resp.json()["meta"]["total_count"], 0) + + def test_will_return_keywords_for_the_selected_thesaurus_if_exists(self): + url = f"{self.list_url}?thesaurus=inspire-theme" + resp = self.api_client.get(url) + self.assertValidJSONResponse(resp) + self.assertEqual(resp.json()["meta"]["total_count"], 34) + + def test_will_return_empty_if_the_alt_label_does_not_exists(self): + url = f"{self.list_url}?alt_label=invalid-alt_label" + resp = self.api_client.get(url) + self.assertValidJSONResponse(resp) + self.assertEqual(resp.json()["meta"]["total_count"], 0) + + def test_will_return_keywords_for_the_selected_alt_label_if_exists(self): + url = f"{self.list_url}?alt_label=ac" + resp = self.api_client.get(url) + self.assertValidJSONResponse(resp) + self.assertEqual(resp.json()["meta"]["total_count"], 1) + + def test_will_return_empty_if_the_kaywordId_does_not_exists(self): + url = f"{self.list_url}?id=12365478954862" + resp = self.api_client.get(url) + print(self.deserialize(resp)) + self.assertValidJSONResponse(resp) + self.assertEqual(resp.json()["meta"]["total_count"], 0) + + @patch("geonode.api.api.get_language") + def test_will_return_expected_keyword_label_for_existing_lang(self, lang): + lang.return_value = "de" + url = f"{self.list_url}?thesaurus=inspire-theme" + resp = self.api_client.get(url) + # the german translations exists, for the other labels, the alt_label will be used + expected_labels = [ + "ac", "Adressen", "af", "am", "au", "br", "bu", + "cp", "ef", "el", "er", "ge", "gg", "gn", "hb", "hh", + "hy", "lc", "lu", "mf", "mr", "nz", "of", "oi", "pd", + "pf", "ps", "rs", "sd", "so", "sr", "su", "tn", "us" + ] + actual_labels = [x["alt_label"] for x in self.deserialize(resp)["objects"]] + self.assertValidJSONResponse(resp) + self.assertListEqual(expected_labels, actual_labels) + + @patch("geonode.api.api.get_language") + def test_will_return_default_keyword_label_for_not_existing_lang(self, lang): + lang.return_value = "ke" + url = f"{self.list_url}?thesaurus=inspire-theme" + resp = self.api_client.get(url) + # no translations exists, the alt_label will be used for all keywords + expected_labels = [ + "ac", "ad", "af", "am", "au", "br", "bu", + "cp", "ef", "el", "er", "ge", "gg", "gn", "hb", "hh", + "hy", "lc", "lu", "mf", "mr", "nz", "of", "oi", "pd", + "pf", "ps", "rs", "sd", "so", "sr", "su", "tn", "us" + ] + actual_labels = [x["alt_label"] for x in self.deserialize(resp)["objects"]] + self.assertValidJSONResponse(resp) + self.assertListEqual(expected_labels, actual_labels) diff --git a/geonode/templates/search/_t_keywords_filter.html b/geonode/templates/search/_t_keywords_filter.html index 96579c8ea03..7ff72bf6912 100644 --- a/geonode/templates/search/_t_keywords_filter.html +++ b/geonode/templates/search/_t_keywords_filter.html @@ -5,7 +5,7 @@ {% for tname in THESAURI_FILTERS %}