Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializing and deserializing ResourceBase and Dataset objects breaks validation check #10841

Closed
mwallschlaeger opened this issue Mar 23, 2023 · 0 comments
Assignees
Labels
4.0.x 4.1.x regression Issues related to regressions.

Comments

@mwallschlaeger
Copy link
Member

Expected Behavior

When I have a Dataset object in the database with one of the following properties set ["keywords", "tkeywords", "restriction_code_type", "license", "spatial_representation_type", "category"]and than take this from the database and serialize it into a JSON. I expect that when I deserialize this JSON afterwards, it will not throw any validations errors.

Example script to do so, based on django-rest-framework docs here.

import sys, os, django
sys.path.append("/") #here store is root folder(means parent).
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "store.settings")
django.setup()

import io
from rest_framework.renderers import JSONRenderer
from geonode.layers.api.serializers import 
from geonode.base.models import ResourceBase
from geonode.base.api.serializers import ResourceBaseSerializer
from rest_framework.parsers import JSONParser

r = ResourceBase.objects.all()[0] # check object id here
s = ResourceBaseSerializer(r)
json = JSONRenderer().render(s.data)
stream = io.BytesIO(json)
data = JSONParser().parse(stream)
se = ResourceBaseSerializer(data=data)
se.is_valid()
print(se.validated_data)

Actual Behavior

The is_valid() method runs into the following exception:

see Traceback

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 1823, in get_prep_value
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'dict'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/geonode/examples/test_rest.py", line 21, in <module>
    se.is_valid()
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 220, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 419, in run_validation
    value = self.to_internal_value(data)
  File "/usr/src/geonode/geonode/base/api/serializers.py", line 651, in to_internal_value
    data = super(ResourceBaseSerializer, self).to_internal_value(data)
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/serializers.py", line 708, in to_internal_value
    value = super(WithDynamicSerializerMixin, self).to_internal_value(data)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 476, in to_internal_value
    validated_value = field.run_validation(primitive_value)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/fields.py", line 568, in run_validation
    value = self.to_internal_value(data)
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/fields/fields.py", line 341, in to_internal_value
    return [
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/fields/fields.py", line 342, in <listcomp>
    self.to_internal_value_single(
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/fields/fields.py", line 327, in to_internal_value_single
    instance = related_model.objects.get(pk=data)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 424, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 941, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1416, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1435, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1370, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1216, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/lookups.py", line 25, in __init__
    self.rhs = self.get_prep_lookup()
  File "/usr/local/lib/python3.10/site-packages/django/db/models/lookups.py", line 77, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 1825, in get_prep_value
    raise e.__class__(
TypeError: Field 'id' expected a number but got {'name': 'testkeyword', 'slug': 'testkeyword'}.
root@c2255dad5141:/usr/src/geonode# python examples/test_rest.py 
Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 1823, in get_prep_value
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a real number, not 'dict'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/geonode/examples/test_rest.py", line 18, in <module>
    se.is_valid()
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 220, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 419, in run_validation
    value = self.to_internal_value(data)
  File "/usr/src/geonode/geonode/base/api/serializers.py", line 651, in to_internal_value
    data = super(ResourceBaseSerializer, self).to_internal_value(data)
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/serializers.py", line 708, in to_internal_value
    value = super(WithDynamicSerializerMixin, self).to_internal_value(data)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 476, in to_internal_value
    validated_value = field.run_validation(primitive_value)
  File "/usr/local/lib/python3.10/site-packages/rest_framework/fields.py", line 568, in run_validation
    value = self.to_internal_value(data)
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/fields/fields.py", line 347, in to_internal_value
    return self.to_internal_value_single(data, self.serializer)
  File "/usr/local/lib/python3.10/site-packages/dynamic_rest/fields/fields.py", line 327, in to_internal_value_single
    instance = related_model.objects.get(pk=data)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 424, in get
    clone = self._chain() if self.query.combinator else self.filter(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 941, in filter
    return self._filter_or_exclude(False, args, kwargs)
  File "/usr/local/lib/python3.10/site-packages/modeltranslation/manager.py", line 323, in _filter_or_exclude
    return super(MultilingualQuerySet, self)._filter_or_exclude(negate, args, kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 961, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 968, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1416, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1435, in _add_q
    child_clause, needed_inner = self.build_filter(
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1370, in build_filter
    condition = self.build_lookup(lookups, col, value)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1216, in build_lookup
    lookup = lookup_class(lhs, rhs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/lookups.py", line 25, in __init__
    self.rhs = self.get_prep_lookup()
  File "/usr/local/lib/python3.10/site-packages/django/db/models/lookups.py", line 77, in get_prep_lookup
    return self.lhs.output_field.get_prep_value(self.rhs)
  File "/usr/local/lib/python3.10/site-packages/django/db/models/fields/__init__.py", line 1825, in get_prep_value
    raise e.__class__(
TypeError: Field 'id' expected a number but got {'identifier': 'transportation'}.

This relates to all DynamicRelationField in the ResourceBaseSerializer listed above. The dynamic_rest framework tries to initiate the DynamicRelationField with DynamicRelationField.objects.create_or_get(pk={'identifier': 'transportation'}) in here

This bug also prohibits setting this properties via the REST V2 API.

Steps to Reproduce the Problem

  1. create a dataset with e.g. a category set
  2. run the script above to validate the previously created dataset

Specifications

  • GeoNode version: 4.0.3
  • Installation type (vanilla, geonode-project): vanilla
  • Installation method (manual, docker): docker
  • Platform: ubuntu
  • Additional details:
@afabiani afabiani added regression Issues related to regressions. 4.0.x 4.1.x labels Mar 27, 2023
github-actions bot pushed a commit that referenced this issue Aug 23, 2023
…t objects breaks validation check (#10843)

* issue10841 add convertion to internal types for DynamicModelSerializer

* issue10841 add convertion to internal types for DynamicModelSerializer

* issue10841 add convertion to internal types for DynamicModelSerializer

* issue10841 add convertion to internal types for DynamicModelSerializer

* issue10841 add convertion to internal types for DynamicModelSerializer

* - Fix formatting

---------

Co-authored-by: Giovanni Allegri <giohappy@gmail.com>
Co-authored-by: Alessio Fabiani <alessio.fabiani@geosolutionsgroup.com>
(cherry picked from commit 54d85b0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.0.x 4.1.x regression Issues related to regressions.
Projects
None yet
Development

No branches or pull requests

2 participants