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

Added optional callback SqlalchemyDataLayer.unhandled_exception_forma… #149

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions docs/data_layer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,20 @@ Optional parameters:

:id_field: the field used as identifier field instead of the primary key of the model
:url_field: the name of the parameter in the route to get value to filter with. Instead "id" is used.
:unhandled_exception_formatter: callback function used to format unexpected exceptions in data layer. It accepts caught exception and returns dict of kwargs for JsonApiException initializer.

Example:

.. code-block:: python

def sa_exception_formatter(exc):
return {"detail": "SQLAlchemy complains!", "status": 405}

class ComputerList(ResourceList):
schema = ComputerSchema
data_layer = {'session': db.session,
'model': Computer,
'unhandled_exception_formatter': sa_exception_formatter}

By default SQLAlchemy eagerload related data specified in include querystring parameter. If you want to disable this feature you must add eagerload_includes: False to data layer parameters.

Expand Down
41 changes: 35 additions & 6 deletions flask_rest_jsonapi/data_layers/alchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@ def __init__(self, kwargs):
raise Exception("You must provide a model in data_layer_kwargs to use sqlalchemy data layer in {}"
.format(self.resource.__name__))

def _client_formatted(self, exc):
try:
data = self.unhandled_exception_formatter(exc)

except AttributeError:
data = None

return data

def create_object(self, data, view_kwargs):
"""Create an object through sqlalchemy

Expand Down Expand Up @@ -62,7 +71,11 @@ def create_object(self, data, view_kwargs):
raise e
except Exception as e:
self.session.rollback()
raise JsonApiException("Object creation error: " + str(e), source={'pointer': '/data'})
e_data = self._client_formatted(e)
raise JsonApiException(**(
e_data if e_data
else {"source": {'pointer': '/data'}, "detail": "Object creation error: " + str(e)}
))

self.after_create_object(obj, data, view_kwargs)

Expand Down Expand Up @@ -164,7 +177,11 @@ def update_object(self, obj, data, view_kwargs):
raise e
except Exception as e:
self.session.rollback()
raise JsonApiException("Update object error: " + str(e), source={'pointer': '/data'})
e_data = self._client_formatted(e)
raise JsonApiException(**(
e_data if e_data
else {"source": {'pointer': '/data'}, "detail": "Update object error: " + str(e)}
))

self.after_update_object(obj, data, view_kwargs)

Expand All @@ -190,7 +207,10 @@ def delete_object(self, obj, view_kwargs):
raise e
except Exception as e:
self.session.rollback()
raise JsonApiException("Delete object error: " + str(e))
e_data = self._client_formatted(e)
raise JsonApiException(**(
e_data if e_data else {"detail": "Delete object error: " + str(e)}
))

self.after_delete_object(obj, view_kwargs)

Expand Down Expand Up @@ -247,7 +267,10 @@ def create_relationship(self, json_data, relationship_field, related_id_field, v
raise e
except Exception as e:
self.session.rollback()
raise JsonApiException("Create relationship error: " + str(e))
e_data = self._client_formatted(e)
raise JsonApiException(**(
e_data if e_data else {"detail": "Create relationship error: " + str(e)}
))

self.after_create_relationship(obj, updated, json_data, relationship_field, related_id_field, view_kwargs)

Expand Down Expand Up @@ -346,7 +369,10 @@ def update_relationship(self, json_data, relationship_field, related_id_field, v
raise e
except Exception as e:
self.session.rollback()
raise JsonApiException("Update relationship error: " + str(e))
e_data = self._client_formatted(e)
raise JsonApiException(**(
e_data if e_data else {"detail": "Update relationship error: " + str(e)}
))

self.after_update_relationship(obj, updated, json_data, relationship_field, related_id_field, view_kwargs)

Expand Down Expand Up @@ -396,7 +422,10 @@ def delete_relationship(self, json_data, relationship_field, related_id_field, v
raise e
except Exception as e:
self.session.rollback()
raise JsonApiException("Delete relationship error: " + str(e))
e_data = self._client_formatted(e)
raise JsonApiException(**(
e_data if e_data else {"detail": "Delete relationship error: " + str(e)}
))

self.after_delete_relationship(obj, updated, json_data, relationship_field, related_id_field, view_kwargs)

Expand Down