Skip to content

Commit

Permalink
Merge pull request #124 from zalf-rdm/issue_#109_Bug_Unable_set_keywo…
Browse files Browse the repository at this point in the history
…rds_on_geonode_objects_when_defining_keyword_via_API

[Fixes #109] Bug: Unable set keywords on geonode_objects when definin…
  • Loading branch information
mwallschlaeger authored Jun 18, 2024
2 parents 5448c52 + 52b9d55 commit 0ab6376
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 3 deletions.
55 changes: 54 additions & 1 deletion geonode/base/api/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@
from rest_framework.exceptions import ParseError
from dynamic_rest.fields.fields import DynamicRelationField

from geonode.base.models import RelatedIdentifierType, RelationType, RelatedIdentifier, FundingReference, Funder
from geonode.base.models import (
RelatedIdentifierType,
RelationType,
RelatedIdentifier,
FundingReference,
Funder,
HierarchicalKeyword,
)


class RelatedIdentifierDynamicRelationField(DynamicRelationField):
Expand Down Expand Up @@ -56,6 +63,52 @@ def to_internal_value_single(self, data, serializer):
return funder[0]


class KeywordsDynamicRelationField(DynamicRelationField):
def to_internal_value_single(self, data, serializer):
"""Overwrite of DynamicRelationField implementation to handle complex data structure initialization
Args:
data (Union[str, Dict]}): serialized or deserialized data from http calls (POST, GET ...),
if content-type application/json is used, data shows up as dict
serializer (DynamicModelSerializer): Serializer for the given data
Raises:
ValidationError: raised when requested data does not exist
django.db.models.QuerySet: return QuerySet object of the request or set data
"""

related_model = serializer.Meta.model
try:
if isinstance(data, str):
data = json.loads(data)
except ValueError:
return super().to_internal_value_single(data, serializer)

if not isinstance(data, dict):
return super().to_internal_value_single(data, serializer)

def __set_full_keyword__(d):
if "name" not in d:
raise ValidationError('No "name" object found for given keyword ...')
if "slug" not in d:
d["slug"] = d["name"]
if "depth" not in d:
d["depth"] = 1
if "path" not in d:
d["path"] = d["name"]
return d

data = __set_full_keyword__(data)
keyword = HierarchicalKeyword.objects.filter(name=data["name"]).first()
if keyword is None:
keyword = HierarchicalKeyword.objects.create(
name=data["name"], slug=data["slug"], depth=data["depth"], path=data["path"]
)
keyword.save()
return keyword


class ComplexDynamicRelationField(DynamicRelationField):
def to_internal_value_single(self, data, serializer):
"""Overwrite of DynamicRelationField implementation to handle complex data structure initialization
Expand Down
5 changes: 3 additions & 2 deletions geonode/base/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
ComplexDynamicRelationField,
RelatedIdentifierDynamicRelationField,
FundersDynamicRelationField,
KeywordsDynamicRelationField,
)
from geonode.layers.utils import get_dataset_download_handlers, get_default_dataset_download_handler
from geonode.utils import build_absolute_uri
Expand Down Expand Up @@ -703,7 +704,7 @@ def __init__(self, *args, **kwargs):
self.fields["sourcetype"] = serializers.CharField(read_only=True)
self.fields["embed_url"] = EmbedUrlField(required=False)
self.fields["thumbnail_url"] = ThumbnailUrlField(read_only=True)
self.fields["keywords"] = ComplexDynamicRelationField(
self.fields["keywords"] = KeywordsDynamicRelationField(
SimpleHierarchicalKeywordSerializer, embed=False, many=True
)
self.fields["tkeywords"] = ComplexDynamicRelationField(SimpleThesaurusKeywordSerializer, embed=False, many=True)
Expand Down Expand Up @@ -882,7 +883,7 @@ def save(self, **kwargs):
instance = super().save(**kwargs)
if keywords is not None:
instance.keywords.clear()
[instance.keywords.add(keyword) for keyword in keywords]
[instance.keywords.add(keyword.name) for keyword in keywords]
if extent and instance.get_real_instance()._meta.model in api_bbox_settable_resource_models:
srid = extent.get("srid", "EPSG:4326")
coords = extent.get("coords")
Expand Down

0 comments on commit 0ab6376

Please sign in to comment.