miLibris / flask-rest-jsonapi

Flask extension to build REST APIs around JSONAPI 1.0 specification.
http://flask-rest-jsonapi.readthedocs.io
MIT License
597 stars 153 forks source link

Relationship mix sqlalchemy and custom datalayer #128

Closed kumy closed 5 years ago

kumy commented 6 years ago

It is currently not possible to have a relationships where the destination is managed by custom_datalayer.

In my case when GeokretTypeDetail is using a custom class as backend datalayer, when used, it raise this JSonApiError:

{u'errors': [{u'detail': u'mapper',
              u'source': u'',
              u'status': 500,
              u'title': u'Unknown error'}],
 u'jsonapi': {u'version': u'1.0'}}

which when not captured is:

  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/api.py", line 133, in decorated
    self.check_permissions(view, view_args, view_kwargs, *args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/app/api/helpers/permission_manager.py", line 191, in permission_manager
    permissions[args[0]](view, view_args, view_kwargs, *args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/app/api/helpers/permissions.py", line 20, in decorator
    return fn(*args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/app/api/helpers/permission_manager.py", line 65, in is_owner
    return view(*view_args, **view_kwargs)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/decorators.py", line 32, in wrapper
    return func(*args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask/views.py", line 88, in view
    return self.dispatch_request(*args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/resource.py", line 64, in dispatch_request
    response = method(*args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/decorators.py", line 56, in wrapper
    return func(*args, **kwargs)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/resource.py", line 258, in patch
    self._data_layer.update_object(obj, data, kwargs)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/data_layers/alchemy.py", line 125, in update_object
    self.apply_relationships(data, obj)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/flask_rest_jsonapi/data_layers/alchemy.py", line 386, in apply_relationships
    related_model = getattr(obj.__class__, key).property.mapper.class_
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 853, in __getattr__
    return self._fallback_getattr(key)
  File "/home/kumy/GIT/geokrety-api/venv/local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 831, in _fallback_getattr
    raise AttributeError(key)
AttributeError: mapper

Extract of my schemas:

class GeokretSchemaPublic(Schema):
    id = fields.Str(dump_only=True)
    name = fields.Str(required=True)

    type = Relationship(
        attribute='type',
        self_view='v1.geokret_type',
        self_view_kwargs={'id': '<id>'},
        related_view='v1.geokrety_type_details',
        related_view_kwargs={'geokret_id': '<id>'},
        schema='GeoKretyTypesSchema',
        type_='type',
        include_resource_linkage=True,
    )

class GeoKretyTypesSchema(Schema):
    class Meta:
        type_ = 'geokrety-type'
        self_view = 'v1.geokrety_type_details'
        self_view_kwargs = {'id': '<id>'}
        self_view_many = 'v1.geokrety_type_list'
        inflect = dasherize
        strict = True
        ordered = True

    id = fields.Str(dump_only=True)
    name = fields.Str(required=True)

class GeokretTypeDetail(ResourceDetail):
    methods = ['GET']
    schema = GeoKretyTypesSchema
    data_layer = {
        'class': GeoKretyTypeDataLayer
    }
kumy commented 6 years ago

Please find PR #129

akira-dev commented 5 years ago

I have closed this PR because I think this feature is related to a custom data layer