API Bundle

Integrates Marshmallow and APISpec with SQLAlchemy and Flask Unchained.

Installation

Install dependencies:

pip install "flask-unchained[api]"

And enable the API bundle in your unchained_config.py:

# your_project_root/unchained_config.py

BUNDLES = [
    # ...
    'flask_unchained.bundles.api',
    'app',
]

Usage

The API bundle includes two extensions, Api and Marshmallow. The Api extension is used for generating OpenAPI documentation and the Marshmallow extension is used for serialization. These should be imported like so:

from flask_unchained.bundles.api import api, ma

Model Serializers

ModelSerializer is very similar to Flask Marshmallow’s ModelSchema. There are two differences:

  • dependency injection is automatically set up, and

  • we automatically convert field names to/from camel case when dumping/loading (although this is customizable)

Let’s say you have the following model:

# your_bundle/models.py

from flask_unchained.bundles.sqlalchemy import db

class User(db.Model):
    name = db.Column(db.String)
    email = db.Column(db.String)
    password = db.Column(db.String)

A simple serializer for it would look like this:

# your_bundle/serializers.py

from flask_unchained.bundles.api import ma

from .models import User


class UserSerializer(ma.ModelSerializer):
    class Meta:
        model = User

One gotchya here is that Marshmallow has no way to know that the email column should use an email field. Therefore, we need to help it out a bit:

# your_bundle/serializers.py

from flask_unchained.bundles.api import ma

from .models import User


class UserSerializer(ma.ModelSerializer):
    class Meta:
        model = User
        load_only = ('password',)

    email = ma.Email(required=True)

There are three separate contexts for (de)serialization:

  • standard: dumping/loading a single object

  • many: dumping/loading multiple objects

  • create: creating a new object

By default, any serializers you define will be used for all three. This can be customized:

# your_bundle/serializers.py

from flask_unchained.bundles.api import ma

@ma.serializer(many=True)
class UserSerializerMany(ma.ModelSerializer):
    # ...

@ma.serializer(create=True)
class UserSerializerCreate(ma.ModelSerializer):
    # ...

Let’s make a model resource so we’ll have API routes for it:

Model Resources

# your_bundle/views.py

from flask_unchained.bundles.api import ModelResource

from .models import User


class UserResource(ModelResource):
    class Meta:
        model = User

Add it to your routes:

# your_app_bundle/routes.py

routes = lambda: [
    prefix('/api/v1', [
        resource('/users', UserResource),
    ],
]

And that’s it, unless you need to customize any behavior.

Model Resource Meta Options

ModelResource inherits all of the meta options from Controller and Resource, and it adds some options of its own:

meta option name

description

default value

model

The model class to use for the resource.

None (it’s required to be set by you)

serializer

The serializer instance to use for (de)serializing an individual model.

Determined automatically by the model name. Can be set manually to override the automatic discovery.

serializer_create

The serializer instance to use for loading data for creation of a new model.

Determined automatically by the model name. Can be set manually to override the automatic discovery.

serializer_many

The serializer instance to use for (de)serializing a list of models.

Determined automatically by the model name. Can be set manually to override the automatic discovery.

include_methods

A list of resource methods to automatically include.

('list', 'create', 'get', 'patch', 'put', 'delete')

exclude_methods

A list of resource methods to exclude.

()

include_decorators

A list of resource methods for which to automatically apply the default decorators.

('list', 'create', 'get', 'patch', 'put', 'delete')

exclude_decorators

A list of resource methods for which to not automatically apply the default decorators.

()

method_decorators

This can either be a list of decorators to apply to all methods, or a dictionary of method names to a list of decorators to apply for each method. In both cases, decorators specified here are run before the default decorators.

()

API Docs

See API Bundle API