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 %}