API Bundle ---------- Integrates `Marshmallow `_ and `APISpec `_ with SQLAlchemy and Flask Unchained. Installation ^^^^^^^^^^^^ Install dependencies: .. code:: bash pip install "flask-unchained[api]" And enable the API bundle in your ``unchained_config.py``: .. code:: python # your_project_root/unchained_config.py BUNDLES = [ # ... 'flask_unchained.bundles.api', 'app', ] Usage ^^^^^ The API bundle includes two extensions, :class:`~flask_unchained.bundles.api.Api` and :class:`~flask_unchained.bundles.api.Marshmallow`. The :class:`~flask_unchained.bundles.api.Api` extension is used for generating OpenAPI documentation and the :class:`~flask_unchained.bundles.api.Marshmallow` extension is used for serialization. These should be imported like so: .. code:: python from flask_unchained.bundles.api import api, ma Model Serializers ~~~~~~~~~~~~~~~~~ :class:`~flask_unchained.bundles.api.ModelSerializer` is very similar to Flask Marshmallow's :class:`~flask_marshmallow.sqla.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: .. code:: python # 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: .. code:: python # 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: .. code:: python # 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: .. code:: python # 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 ~~~~~~~~~~~~~~~ .. code:: python # 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: .. code:: python # 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** :class:`~flask_unchained.bundles.api.ModelResource` inherits all of the meta options from :class:`~flask_unchained.Controller` and :class:`~flask_unchained.Resource`, and it adds some options of its own: .. list-table:: :widths: 20 40 40 :header-rows: 1 * - 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 :doc:`../api/api-bundle`