To those who use Flask, setting up SQLAlchemy-JSONAPI can be extremely complex and frustrating. Let’s look at an example:
from sqlalchemy_jsonapi import FlaskJSONAPI app = Flask(__name__) db = SQLAlchemy(app) api = FlaskJSONAPI(app, db)
And after all that work, you should now have a full working API.
As Flask makes use of signals via Blinker, it would be appropriate to make use of them in the Flask module for SQLALchemy-JSONAPI. If a signal receiver returns a value, it can alter the final response.
Triggered before serialization:
@api.on_request.connect def process_api_request(sender, method, endpoint, data, req_args): # Handle the request
Triggered after successful serialization:
@api.on_success.connect def process_api_success(sender, method, endpoint, data, req_args, response): # Handle the response dictionary
Triggered after failed handling:
@api.on_error.connect def process_api_error(sender, method, endpoint, data, req_args, error): # Handle the error
Triggered after rendering of response:
@api.on_response.connect def process_api_response(sender, method, endpoint, data, req_args, rendered_response): # Handle the rendered response
Wrapping the Handlers¶
While signals provide some control, sometimes you want to wrap or override the handler for the particular endpoint and method. This can be done through a specialized decorator that allows you to specify in what cases you want the handler wrapped:
@api.wrap_handler(['users'], [Methods.GET], [Endpoints.COLLECTION, Endpoints.RESOURCE]) def log_it(next, *args, **kwargs): logging.info('In a wrapped handler!') return next(*args, **kwargs)
Handlers are placed into a list and run in order of placement within the list. That means you can perform several layers of checks and override as needed.