Flask-Marshmallow: Flask + marshmallow for beautiful APIs

changelog // github // pypi // issues

Flask + marshmallow for beautiful APIs

Flask-Marshmallow is a thin integration layer for Flask (a Python web framework) and marshmallow (an object serialization/deserialization library) that adds additional features to marshmallow, including URL and Hyperlinks fields for HATEOAS-ready APIs. It also (optionally) integrates with Flask-SQLAlchemy.

Get it now

pip install flask-marshmallow

Create your app.

from flask import Flask, jsonify
from flask_marshmallow import Marshmallow

app = Flask(__name__)
ma = Marshmallow(app)

Write your models.

from your_orm import Model, Column, Integer, String, DateTime

class User(Model):
    email = Column(String)
    password = Column(String)
    date_created = Column(DateTime, auto_now_add=True)

Define your output format with marshmallow.

class UserSchema(ma.Schema):
    class Meta:
        # Fields to expose
        fields = ('email', 'date_created', '_links')
    # Smart hyperlinking
    _links = ma.Hyperlinks({
        'self': ma.URLFor('author_detail', id='<id>'),
        'collection': ma.URLFor('authors')
    })

user_schema = UserSchema()
users_schema = UserSchema(many=True)

Output the data in your views.

@app.route('/api/users/')
def users():
    all_users = User.all()
    result = users_schema.dump(all_users)
    return jsonify(result.data)
    # OR
    # return user_schema.jsonify(all_users)

@app.route('/api/users/<id>')
def user_detail(id):
    user = User.get(id)
    return user_schema.jsonify(user)
# {
#     "email": "fred@queen.com",
#     "date_created": "Fri, 25 Apr 2014 06:02:56 -0000",
#     "_links": {
#         "self": "/api/authors/42",
#         "collection": "/api/authors/"
#     }
# }

Optional Flask-SQLAlchemy Integration

Flask-Marshmallow includes useful extras for integrating with Flask-SQLAlchemy and marshmallow-sqlalchemy.

To enable SQLAlchemy integration, make sure that both Flask-SQLAlchemy and marshmallow-sqlalchemy are installed.

pip install -U flask-sqlalchemy marshmallow-sqlalchemy

Next, initialize the SQLAlchemy and Marshmallow extensions, in that order.

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'

# Order matters: Initialize SQLAlchemy before Marshmallow
db = SQLAlchemy(app)
ma = Marshmallow(app)

Note on initialization order

Flask-SQLAlchemy must be initialized before Flask-Marshmallow.

Declare your models like normal.

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))

class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(255))
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'))
    author = db.relationship('Author', backref='books')

Generate marshmallow Schemas from your models using ModelSchema.

class AuthorSchema(ma.ModelSchema):
    class Meta:
        model = Author

class BookSchema(ma.ModelSchema):
    class Meta:
        model = Book

You can now use your schema to dump and load your ORM objects.

>>> db.create_all()
>>> author_schema = AuthorSchema()
>>> book_schema = BookSchema()
>>> author = Author(name='Chuck Paluhniuk')
>>> book = Book(title='Fight Club', author=author)
>>> db.session.add(author)
>>> db.session.add(book)
>>> db.session.commit()
>>> author_schema.dump(author).data
{'id': 1, 'name': 'Chuck Paluhniuk', 'books': [1]}

ModelSchema is nearly identical in API to marshmallow_sqlalchemy.ModelSchema with the following exceptions:

Note: By default, Flask’s jsonify method sorts the list of keys and returns consistent results to ensure that external HTTP caches aren’t trashed. As a side effect, this will override ordered=True in the ModelSchema’s class Meta (if you set it). To disable this, set JSON_SORT_KEYS=False in your Flask app config. In production it’s recommended to let jsonify sort the keys and not set ordered=True in your ModelSchema in order to minimize generation time and maximize cachability of the results.

You can also use ma.HyperlinkRelated fields if you want relationships to be represented by hyperlinks rather than primary keys.

class BookSchema(ma.ModelSchema):
    class Meta:
        model = Book
    author = ma.HyperlinkRelated('author_detail')
>>> with app.test_request_context():
...     print(book_schema.dump(book).data)
{'id': 1, 'title': 'Fight Club', 'author': '/authors/1'}

The first argument to the HyperlinkRelated constructor is the name of the view used to generate the URL, just as you would pass it to the url_for function. If your models and views use the id attribute as a primary key, you’re done; otherwise, you must specify the name of the attribute used as the primary key.

To represent a one-to-many relationship, wrap the HyperlinkRelated instance in a marshmallow.fields.List field, like this:

class AuthorSchema(ma.ModelSchema):
    class Meta:
        model = Author
    books = ma.List(ma.HyperlinkRelated('book_detail'))
>>> with app.test_request_context():
...     print(author_schema.dump(author).data)
{'id': 1, 'name': 'Chuck Paluhniuk', 'books': ['/books/1']}

API

flask_marshmallow

Integrates the marshmallow serialization/deserialization library with your Flask application.

copyright:
  1. 2014-2016 by Steven Loria
license:

MIT, see LICENSE for more details.

class flask_marshmallow.Marshmallow(app=None)

Wrapper class that integrates Marshmallow with a Flask application.

To use it, instantiate with an application:

from flask import Flask

app = Flask(__name__)
ma = Marshmallow(app)

The object provides access to the Schema class, all fields in marshmallow.fields, as well as the Flask-specific fields in flask_marshmallow.fields.

You can declare schema like so:

class BookSchema(ma.Schema):
    class Meta:
        fields = ('id', 'title', 'author', 'links')

    author = ma.Nested(AuthorSchema)

    links = ma.Hyperlinks({
        'self': ma.URLFor('book_detail', id='<id>'),
        'collection': ma.URLFor('book_list')
    })

In order to integrate with Flask-SQLAlchemy, this extension must by initialized after flask_sqlalchemy.SQLAlchemy.

db = SQLAlchemy(app)
ma = Marshmallow(app)

This gives you access to ma.ModelSchema, which generates a marshmallow Schema based on the passed in model.

class AuthorSchema(ma.ModelSchema):
    class Meta:
        model = Author
Parameters:app (Flask) – The Flask application object.
init_app(app)

Initializes the application with the extension.

Parameters:app (Flask) – The Flask application object.
class flask_marshmallow.Schema(extra=None, only=(), exclude=(), prefix=u'', strict=False, many=False, context=None, load_only=(), dump_only=(), partial=False)

Base serializer with which to define custom serializers.

See marshmallow.Schema for more details about the Schema API.

jsonify(obj, many=<object object>, *args, **kwargs)

Return a JSON response containing the serialized data.

Parameters:
  • obj – Object to serialize.
  • many (bool) – Whether obj should be serialized as an instance or as a collection. If unset, defaults to the value of the many attribute on this Schema.
  • kwargs – Additional keyword arguments passed to flask.jsonify.

Changed in version 0.6.0: Takes the same arguments as marshmallow.Schema.dump. Additional keyword arguments are passed to flask.jsonify.

Changed in version 0.6.3: The many argument for this method defaults to the value of the many attribute on the Schema. Previously, the many argument of this method defaulted to False, regardless of the value of Schema.many.

flask_marshmallow.pprint(obj, *args, **kwargs)

Pretty-printing function that can pretty-print OrderedDicts like regular dictionaries. Useful for printing the output of marshmallow.Schema.dump().

flask_marshmallow.fields

Custom, Flask-specific fields.

See the marshmallow.fields module for the list of all fields available from the marshmallow library.

class flask_marshmallow.fields.URLFor(endpoint, **kwargs)

Field that outputs the URL for an endpoint. Acts identically to Flask’s url_for function, except that arguments can be pulled from the object to be serialized.

Usage:

url = URLFor('author_get', id='<id>')
https_url = URLFor('author_get', id='<id>', _scheme='https', _external=True)
Parameters:
  • endpoint (str) – Flask endpoint name.
  • kwargs – Same keyword arguments as Flask’s url_for, except string arguments enclosed in < > will be interpreted as attributes to pull from the object.
flask_marshmallow.fields.UrlFor

alias of URLFor

class flask_marshmallow.fields.AbsoluteURLFor(endpoint, **kwargs)

Field that outputs the absolute URL for an endpoint.

flask_marshmallow.fields.AbsoluteUrlFor

alias of AbsoluteURLFor

Field that outputs a dictionary of hyperlinks, given a dictionary schema with URLFor objects as values.

Example:

_links = Hyperlinks({
    'self': URLFor('author', id='<id>'),
    'collection': URLFor('author_list'),
    }
})

URLFor objects can be nested within the dictionary.

_links = Hyperlinks({
    'self': {
        'href': URLFor('book', id='<id>'),
        'title': 'book detail'
    }
})
Parameters:schema (dict) – A dict that maps names to URLFor fields.

flask_marshmallow.sqla

Integration with Flask-SQLAlchemy and marshmallow-sqlalchemy. Provides ModelSchema classes that use the scoped session from Flask-SQLALchemy.

class flask_marshmallow.sqla.DummySession

Placeholder session object.

class flask_marshmallow.sqla.HyperlinkRelated(endpoint, url_key='id', external=False, **kwargs)

Field that generates hyperlinks to indicate references between models, rather than primary keys.

Parameters:
  • endpoint (str) – Flask endpoint name for generated hyperlink.
  • url_key (str) – The attribute containing the reference’s primary key. Defaults to “id”.
  • external (bool) – Set to True if absolute URLs should be used, instead of relative URLs.
class flask_marshmallow.sqla.ModelSchema(*args, **kwargs)

ModelSchema that generates fields based on the model class Meta option, which should be a db.Model class from flask_sqlalchemy. Uses the scoped session from Flask-SQLAlchemy by default.

See marshmallow_sqlalchemy.ModelSchema for more details on the ModelSchema API.

OPTIONS_CLASS

alias of SchemaOpts

class flask_marshmallow.sqla.SchemaOpts(meta)

Schema options for ModelSchema. Same as marshmallow_sqlalchemy.SchemaOpts, except that we add a placeholder DummySession if sqla_session is not defined on class Meta. The actual session from flask_sqlalchemy gets bound in flask_marshmallow.Marshmallow.init_app.

Project Info