From 1f186baa56400a7307090f6b7c72d0b4abbd9ae4 Mon Sep 17 00:00:00 2001 From: Luca Bellenghi Date: Mon, 20 Nov 2023 11:57:42 +0100 Subject: [PATCH 1/3] update serializer for geolocation --- .../restapi/serializers/summary.py | 39 +++++++++++++++---- .../plone/contenttypes/tests/test_ct_luogo.py | 37 ++++++++++++++++++ 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/design/plone/contenttypes/restapi/serializers/summary.py b/src/design/plone/contenttypes/restapi/serializers/summary.py index 9b3dfb90..2fecd709 100644 --- a/src/design/plone/contenttypes/restapi/serializers/summary.py +++ b/src/design/plone/contenttypes/restapi/serializers/summary.py @@ -12,6 +12,7 @@ from plone.app.contenttypes.interfaces import IEvent from plone.app.contenttypes.interfaces import INewsItem from plone.base.interfaces import IImageScalesAdapter +from plone.formwidget.geolocation.geolocation import Geolocation from plone.restapi.interfaces import ISerializeToJsonSummary from plone.restapi.serializer.converters import json_compatible from Products.CMFPlone.utils import safe_hasattr @@ -115,6 +116,35 @@ def get_taxonomy_information_by_type(res, context): return res +def extract_geolocation(context, res): + """ + Extracts geolocation information from the provided context or res. + """ + # Check if latitude and longitude are already present in res + latitude = res.get("latitude", 0) + longitude = res.get("longitude", 0) + + if latitude and longitude: + return {"latitude": latitude, "longitude": longitude} + + # Check if context is an ICatalogBrain and has latitude and longitude + if ICatalogBrain.providedBy(context): + latitude = context.latitude + longitude = context.longitude + if latitude and longitude: + return {"latitude": latitude, "longitude": longitude} + + # Check if context has a geolocation attribute with latitude and longitude + geolocation = getattr(context, 'geolocation', None) + if isinstance(geolocation, Geolocation): + latitude = geolocation.latitude + longitude = geolocation.longitude + if latitude and longitude: + return {"latitude": latitude, "longitude": longitude} + + return None + + @implementer(ISerializeToJsonSummary) @adapter(Interface, IDesignPloneContenttypesLayer) class DefaultJSONSummarySerializer(BaseSerializer): @@ -132,14 +162,7 @@ def __call__(self, force_all_metadata=False, force_images=False): if "geolocation" in metadata_fields or self.show_all_metadata_fields: # backward compatibility for some block templates if "geolocation" not in res: - res["geolocation"] = None - latitude = res.get("latitude", 0) - longitude = res.get("longitude", 0) - if latitude and longitude: - res["geolocation"] = { - "latitude": latitude, - "longitude": longitude, - } + res['geolocation'] = extract_geolocation(self.context, res) res["id"] = self.context.id diff --git a/src/design/plone/contenttypes/tests/test_ct_luogo.py b/src/design/plone/contenttypes/tests/test_ct_luogo.py index fef1180b..d8827552 100644 --- a/src/design/plone/contenttypes/tests/test_ct_luogo.py +++ b/src/design/plone/contenttypes/tests/test_ct_luogo.py @@ -11,6 +11,7 @@ from plone.app.testing import SITE_OWNER_NAME from plone.app.testing import SITE_OWNER_PASSWORD from plone.app.testing import TEST_USER_ID +from plone.formwidget.geolocation import Geolocation from plone.restapi.testing import RelativeSession from Products.CMFPlone.utils import getToolByName from transaction import commit @@ -205,3 +206,39 @@ def test_venue_news(self): res["related_news"][1]["@id"], self.news.absolute_url(), ) + + def test_venue_serializers(self): + venue1 = api.content.create( + container=self.portal, + type="Venue", + title="venue1" + ) + venue1.geolocation = Geolocation(44.35, 11.70) + venue2 = api.content.create( + container=self.portal, + type="Venue", + title="venue2" + ) + venue2.geolocation = Geolocation(44.35, 11.70) + intids = getUtility(IIntIds) + venue_rel = RelationValue(intids.getId(venue2)) + venue1.luoghi_correlati = [venue_rel] + commit() + response = self.api_session.post( + "/@querystring-search", + json={ + "metadata_fields": "_all", + "query": [ + { + "i": "portal_type", + "o": "plone.app.querystring.operation.selection.is", + "v": ["Venue"], + } + ] + }, + ) + items = response.json()['items'] + for item in items: + if item['id'] in ['venue1', 'venue2']: + self.assertEqual(item['geolocation']['latitude'], 44.35) + self.assertEqual(item['geolocation']['longitude'], 11.7) From e2d066b3eba29fc23d16687fc31ba373fa744a5e Mon Sep 17 00:00:00 2001 From: Luca Bellenghi Date: Mon, 20 Nov 2023 12:03:03 +0100 Subject: [PATCH 2/3] black on code --- .../restapi/serializers/summary.py | 4 ++-- .../plone/contenttypes/tests/test_ct_luogo.py | 22 ++++++------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/design/plone/contenttypes/restapi/serializers/summary.py b/src/design/plone/contenttypes/restapi/serializers/summary.py index 2fecd709..05364e14 100644 --- a/src/design/plone/contenttypes/restapi/serializers/summary.py +++ b/src/design/plone/contenttypes/restapi/serializers/summary.py @@ -135,7 +135,7 @@ def extract_geolocation(context, res): return {"latitude": latitude, "longitude": longitude} # Check if context has a geolocation attribute with latitude and longitude - geolocation = getattr(context, 'geolocation', None) + geolocation = getattr(context, "geolocation", None) if isinstance(geolocation, Geolocation): latitude = geolocation.latitude longitude = geolocation.longitude @@ -162,7 +162,7 @@ def __call__(self, force_all_metadata=False, force_images=False): if "geolocation" in metadata_fields or self.show_all_metadata_fields: # backward compatibility for some block templates if "geolocation" not in res: - res['geolocation'] = extract_geolocation(self.context, res) + res["geolocation"] = extract_geolocation(self.context, res) res["id"] = self.context.id diff --git a/src/design/plone/contenttypes/tests/test_ct_luogo.py b/src/design/plone/contenttypes/tests/test_ct_luogo.py index d8827552..2827e1fc 100644 --- a/src/design/plone/contenttypes/tests/test_ct_luogo.py +++ b/src/design/plone/contenttypes/tests/test_ct_luogo.py @@ -208,17 +208,9 @@ def test_venue_news(self): ) def test_venue_serializers(self): - venue1 = api.content.create( - container=self.portal, - type="Venue", - title="venue1" - ) + venue1 = api.content.create(container=self.portal, type="Venue", title="venue1") venue1.geolocation = Geolocation(44.35, 11.70) - venue2 = api.content.create( - container=self.portal, - type="Venue", - title="venue2" - ) + venue2 = api.content.create(container=self.portal, type="Venue", title="venue2") venue2.geolocation = Geolocation(44.35, 11.70) intids = getUtility(IIntIds) venue_rel = RelationValue(intids.getId(venue2)) @@ -234,11 +226,11 @@ def test_venue_serializers(self): "o": "plone.app.querystring.operation.selection.is", "v": ["Venue"], } - ] + ], }, ) - items = response.json()['items'] + items = response.json()["items"] for item in items: - if item['id'] in ['venue1', 'venue2']: - self.assertEqual(item['geolocation']['latitude'], 44.35) - self.assertEqual(item['geolocation']['longitude'], 11.7) + if item["id"] in ["venue1", "venue2"]: + self.assertEqual(item["geolocation"]["latitude"], 44.35) + self.assertEqual(item["geolocation"]["longitude"], 11.7) From 10d137eda02bd138a15478011fcc9ce74ac5ee8c Mon Sep 17 00:00:00 2001 From: Luca Bellenghi Date: Mon, 20 Nov 2023 14:14:33 +0100 Subject: [PATCH 3/3] made code clearer --- CHANGES.rst | 3 ++- .../contenttypes/restapi/serializers/summary.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 53e49c51..56bb6060 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,8 @@ Changelog 6.1.1 (unreleased) ------------------ -- Nothing changed yet. +- Update default summary serializer to better handle geolocation information. + [lucabel] 6.1.0 (2023-11-07) diff --git a/src/design/plone/contenttypes/restapi/serializers/summary.py b/src/design/plone/contenttypes/restapi/serializers/summary.py index 05364e14..da59564c 100644 --- a/src/design/plone/contenttypes/restapi/serializers/summary.py +++ b/src/design/plone/contenttypes/restapi/serializers/summary.py @@ -133,14 +133,14 @@ def extract_geolocation(context, res): longitude = context.longitude if latitude and longitude: return {"latitude": latitude, "longitude": longitude} - - # Check if context has a geolocation attribute with latitude and longitude - geolocation = getattr(context, "geolocation", None) - if isinstance(geolocation, Geolocation): - latitude = geolocation.latitude - longitude = geolocation.longitude - if latitude and longitude: - return {"latitude": latitude, "longitude": longitude} + else: + # Check if context has a geolocation attribute with latitude and longitude + geolocation = getattr(context, "geolocation", None) + if isinstance(geolocation, Geolocation): + latitude = geolocation.latitude + longitude = geolocation.longitude + if latitude and longitude: + return {"latitude": latitude, "longitude": longitude} return None