Callbacks - flarchitect
Description: Callbacks let you hook into the request lifecycle to run custom logic around database operations and responses. They can be declared globally in the Flask configuration or on individual SQLAlchemy ...

Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
View this page
Toggle table of contents sidebar

# Callbacks

Callbacks let you hook into the request lifecycle to run custom logic around database operations and responses. They can be declared globally in the Flask configuration or on individual SQLAlchemy models.

## Callback types

flarchitect recognises a number of callback hooks that allow you to run custom logic at various stages of processing:

- Global setup – runs before any model-specific processing. `GLOBAL_SETUP_CALLBACK` (global: `API_GLOBAL_SETUP_CALLBACK`)

- Setup – runs before database operations. Useful for validation, logging or altering incoming data. `SETUP_CALLBACK` (global: `API_SETUP_CALLBACK`)

- Filter – lets you adjust the SQLAlchemy query object before filtering and pagination are applied. `FILTER_CALLBACK` (global: `API_FILTER_CALLBACK`)

- Add – called before a new object is committed to the database. `ADD_CALLBACK` (global: `API_ADD_CALLBACK`)

- Update – invoked prior to persisting updates to an existing object. `UPDATE_CALLBACK` (global: `API_UPDATE_CALLBACK`)

- Remove – executed before an object is deleted. `REMOVE_CALLBACK` (global: `API_REMOVE_CALLBACK`)

- Return – runs after the database operation but before the response is returned. Ideal for adjusting the output or adding headers. `RETURN_CALLBACK` (global: `API_RETURN_CALLBACK`)

- Dump – executes after Marshmallow serialisation allowing you to modify the dumped data. `DUMP_CALLBACK` (global: `API_DUMP_CALLBACK`)

- Final – runs immediately before the response is sent to the client. `FINAL_CALLBACK` (global: `API_FINAL_CALLBACK`)

- Error – triggered when an exception bubbles up; handle logging or notifications here. `ERROR_CALLBACK` (global: `API_ERROR_CALLBACK`)

## Configuration

Callbacks are referenced by the following configuration keys (global variants use `API_<KEY>`):

- `GLOBAL_SETUP_CALLBACK` / `API_GLOBAL_SETUP_CALLBACK`

- `SETUP_CALLBACK` / `API_SETUP_CALLBACK`

- `FILTER_CALLBACK` / `API_FILTER_CALLBACK`

- `ADD_CALLBACK` / `API_ADD_CALLBACK`

- `UPDATE_CALLBACK` / `API_UPDATE_CALLBACK`

- `REMOVE_CALLBACK` / `API_REMOVE_CALLBACK`

- `RETURN_CALLBACK` / `API_RETURN_CALLBACK`

- `DUMP_CALLBACK` / `API_DUMP_CALLBACK`

- `FINAL_CALLBACK` / `API_FINAL_CALLBACK`

- `ERROR_CALLBACK` / `API_ERROR_CALLBACK`

You can apply these keys in several places:

1. Global Flask config

   Use `API_<KEY>` to apply a callback to all endpoints.

       class Config:
           API_SETUP_CALLBACK = my_setup

2. HTTP method specific config

   Override the global value for a specific method with `API_<METHOD>_<KEY>`.

       class Config:
           API_GET_RETURN_CALLBACK = my_get_return

3. Model config

   Set lowercase attributes on a model’s `Meta` class to apply callbacks to all endpoints for that model.

       class Author(db.Model):
           class Meta:
               setup_callback = my_setup

4. Model method config

   Use `<method>_<key>` on the `Meta` class for the highest level of specificity.

       class Author(db.Model):
           class Meta:
               get_return_callback = my_get_return

## Callback signatures

### Setup, Global setup and filter

Setup-style callbacks should accept `model` and `**kwargs` and return the modified kwargs:

    def my_setup_callback(model, **kwargs):
        # modify kwargs as needed
        return kwargs

    def my_filter_callback(query, model, params):
        return query.filter(model.id > 0)

### Add, update and remove

These callbacks receive the SQLAlchemy object instance and must return it:

    def my_add_callback(obj, model):
        obj.created_by = "system"
        return obj

### Return

Return callbacks receive `model` and `output` and must return a dictionary containing the `output` key:

    def my_return_callback(model, output, **kwargs):
        return {"output": output}

### Dump

Dump callbacks accept `data` and `**kwargs` and must return the data:

    def my_dump_callback(data, **kwargs):
        data["name"] = data["name"].upper()
        return data

### Final

Final callbacks receive the response dictionary before it is serialised:

    def my_final_callback(data):
        data["processed"] = True
        return data

### Error

Error callbacks receive the error message, status code and original value:

    def my_error_callback(error, status_code, value):
        log_exception(error)

## Extending query parameters

Use `ADDITIONAL_QUERY_PARAMS` to document extra query parameters introduced in a return callback. The value is a list of OpenAPI parameter objects.

    class Config:
        API_ADDITIONAL_QUERY_PARAMS = [{
            "name": "log",
            "in": "query",
            "description": "Log call into the database",
            "schema": {"type": "string"},
        }]

    class Author(db.Model):
        class Meta:
            get_additional_query_params = [{
                "name": "log",
                "in": "query",
                "schema": {"type": "string"},
            }]

## Acceptable types

`schema.type` may be one of:

- `string`

- `number`

- `integer`

- `boolean`

- `array`

- `object`

## Acceptable formats

Common `schema.format` values include:

- `date`

- `date-time`

- `password`

- `byte`

- `binary`

- `email`

- `phone`

- `postal_code`

- `uuid`

- `uri`

- `hostname`

- `ipv4`

- `ipv6`

- `int32`

- `int64`

- `float`

- `double`

For comprehensive configuration details see Configuration.