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
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("user_detail", values=dict(id="<id>")),
            "collection": ma.URLFor("users"),
        }
    )


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

Output the data in your views.

@app.route("/api/users/")
def users():
    all_users = User.all()
    return users_schema.dump(all_users)


@app.route("/api/users/<id>")
def user_detail(id):
    user = User.get(id)
    return user_schema.dump(user)


# {
#     "email": "fred@queen.com",
#     "date_created": "Fri, 25 Apr 2014 06:02:56 -0000",
#     "_links": {
#         "self": "/api/users/42",
#         "collection": "/api/users/"
#     }
# }

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 SQLAlchemySchema or SQLAlchemyAutoSchema.

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

    id = ma.auto_field()
    name = ma.auto_field()
    books = ma.auto_field()


class BookSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = Book
        include_fk = True

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)
# {'id': 1, 'name': 'Chuck Paluhniuk', 'books': [1]}

SQLAlchemySchema is nearly identical in API to marshmallow_sqlalchemy.SQLAlchemySchema 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 SQLAlchemySchema’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 SQLAlchemySchema in order to minimize generation time and maximize cacheability 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.SQLAlchemyAutoSchema):
    class Meta:
        model = Book

    author = ma.HyperlinkRelated("author_detail")
with app.test_request_context():
    print(book_schema.dump(book))
# {'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.SQLAlchemyAutoSchema):
    class Meta:
        model = Author

    books = ma.List(ma.HyperlinkRelated("book_detail"))
with app.test_request_context():
    print(author_schema.dump(author))
# {'id': 1, 'name': 'Chuck Paluhniuk', 'books': ['/books/1']}

API

flask_marshmallow

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

class flask_marshmallow.Marshmallow(app: Flask | None = 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", values=dict(id="<id>")),
            "collection": ma.URLFor("book_list"),
        }
    )

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

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

This gives you access to ma.SQLAlchemySchema and ma.SQLAlchemyAutoSchema, which generate marshmallow Schema classes based on the passed in model or table.

class AuthorSchema(ma.SQLAlchemyAutoSchema):
    class Meta:
        model = Author
Parameters:

app (Flask) – The Flask application object.

init_app(app: Flask)

Initializes the application with the extension.

Parameters:

app (Flask) – The Flask application object.

class flask_marshmallow.Schema(*, only: Sequence[str] | AbstractSet[str] | None = None, exclude: Sequence[str] | AbstractSet[str] = (), many: bool = False, context: dict | None = None, load_only: Sequence[str] | AbstractSet[str] = (), dump_only: Sequence[str] | AbstractSet[str] = (), partial: bool | Sequence[str] | AbstractSet[str] | None = None, unknown: str | None = None)

Base serializer with which to define custom serializers.

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

jsonify(obj: Any, many: bool | None = None, *args, **kwargs) Response

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 None, 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) None

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

Deprecated since version 3.7.0: marshmallow.pprint will be removed in marshmallow 4.

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.AbsoluteURLFor(endpoint: str, values: Dict[str, Any] | None = None, **kwargs)

Field that outputs the absolute URL for an endpoint.

flask_marshmallow.fields.AbsoluteUrlFor

alias of AbsoluteURLFor

class flask_marshmallow.fields.Config(key: str, **kwargs)

A field for Flask configuration values.

Examples:

from flask import Flask

app = Flask(__name__)
app.config["API_TITLE"] = "Pet API"


class FooSchema(Schema):
    user = String()
    title = Config("API_TITLE")

This field should only be used in an output schema. A ValueError will be raised if the config key is not found in the app config.

Parameters:

key (str) – The key of the configuration value.

class flask_marshmallow.fields.File(*args, **kwargs)

A binary file field for uploaded files.

Examples:

class ImageSchema(Schema):
    image = File(required=True)
default_error_messages = {'invalid': 'Not a valid file.'}

Default error messages for various kinds of errors. The keys in this dictionary are passed to Field.make_error. The values are error messages passed to marshmallow.exceptions.ValidationError.

deserialize(value: Any, attr: str | None = None, data: Mapping[str, Any] | None = None, **kwargs)

Deserialize value.

Parameters:
  • value – The value to deserialize.

  • attr – The attribute/key in data to deserialize.

  • data – The raw input data passed to Schema.load.

  • kwargs – Field-specific keyword arguments.

Raises:

ValidationError – If an invalid value is passed or if a required value is missing.

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

Example:

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

URLFor objects can be nested within the dictionary.

_links = Hyperlinks(
    {
        "self": {
            "href": URLFor("book", values=dict(id="<id>")),
            "title": "book detail",
        }
    }
)
Parameters:

schema (dict) – A dict that maps names to URLFor fields.

class flask_marshmallow.fields.URLFor(endpoint: str, values: Dict[str, Any] | None = None, **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, and **values should be passed to the values parameter.

Usage:

url = URLFor("author_get", values=dict(id="<id>"))
https_url = URLFor(
    "author_get",
    values=dict(id="<id>", _scheme="https", _external=True),
)
Parameters:
  • endpoint (str) – Flask endpoint name.

  • values (dict) – Same keyword arguments as Flask’s url_for, except string arguments enclosed in < > will be interpreted as attributes to pull from the object.

  • kwargs – keyword arguments to pass to marshmallow field (e.g. required).

flask_marshmallow.fields.UrlFor

alias of URLFor

flask_marshmallow.validate

Custom validation classes for various types of data.

class flask_marshmallow.validate.FileSize(min: str | None = None, max: str | None = None, min_inclusive: bool = True, max_inclusive: bool = True, error: str | None = None)

Validator which succeeds if the file passed to it is within the specified size range. If min is not specified, or is specified as None, no lower bound exists. If max is not specified, or is specified as None, no upper bound exists. The inclusivity of the bounds (if they exist) is configurable. If min_inclusive is not specified, or is specified as True, then the min bound is included in the range. If max_inclusive is not specified, or is specified as True, then the max bound is included in the range.

Example:

class ImageSchema(Schema):
    image = File(required=True, validate=FileSize(min="1 MiB", max="2 MiB"))
Parameters:
  • min – The minimum size (lower bound). If not provided, minimum size will not be checked.

  • max – The maximum size (upper bound). If not provided, maximum size will not be checked.

  • min_inclusive – Whether the min bound is included in the range.

  • max_inclusive – Whether the max bound is included in the range.

  • error – Error message to raise in case of a validation error. Can be interpolated with {input}, {min} and {max}.

class flask_marshmallow.validate.FileType(accept: Iterable[str], error: str | None = None)

Validator which succeeds if the uploaded file is allowed by a given list of extensions.

Example:

class ImageSchema(Schema):
    image = File(required=True, validate=FileType([".png"]))
Parameters:
  • accept – A sequence of allowed extensions.

  • error – Error message to raise in case of a validation error. Can be interpolated with {input} and {extensions}.

flask_marshmallow.sqla

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

class flask_marshmallow.sqla.DummySession

Placeholder session object.

class flask_marshmallow.sqla.HyperlinkRelated(endpoint: str, url_key: str = 'id', external: bool = 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.SQLAlchemyAutoSchema(*args, **kwargs)

SQLAlchemyAutoSchema that automatically generates marshmallow fields from a SQLAlchemy model’s or table’s column. Uses the scoped session from Flask-SQLAlchemy by default.

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

OPTIONS_CLASS

alias of SQLAlchemyAutoSchemaOpts

opts: SchemaOpts = <flask_marshmallow.sqla.SQLAlchemyAutoSchemaOpts object>
class flask_marshmallow.sqla.SQLAlchemyAutoSchemaOpts(meta, **kwargs)
class flask_marshmallow.sqla.SQLAlchemySchema(*args, **kwargs)

SQLAlchemySchema that associates a schema with a model via 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.SQLAlchemySchema for more details on the SQLAlchemySchema API.

OPTIONS_CLASS

alias of SQLAlchemySchemaOpts

opts: SchemaOpts = <flask_marshmallow.sqla.SQLAlchemySchemaOpts object>
class flask_marshmallow.sqla.SQLAlchemySchemaOpts(meta, **kwargs)

Project Info