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:
By default,
SQLAlchemySchema
uses the scoped session created by Flask-SQLAlchemy.SQLAlchemySchema
subclassesflask_marshmallow.Schema
, so it includes thejsonify
method.
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 inmarshmallow.fields
, as well as the Flask-specific fields inflask_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
andma.SQLAlchemyAutoSchema
, which generate marshmallowSchema
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 | None = None, 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 theSchema
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 themany
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 toflask.jsonify
.Changed in version 0.6.3: The
many
argument for this method defaults to the value of themany
attribute on the Schema. Previously, themany
argument of this method defaulted to False, regardless of the value ofSchema.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 tomarshmallow.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.
- class flask_marshmallow.fields.Hyperlinks(schema: Dict[str, URLFor | str], **kwargs)¶
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", } } )
- 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 thevalues
parameter.Usage:
url = URLFor("author_get", values=dict(id="<id>")) https_url = URLFor( "author_get", values=dict(id="<id>", _scheme="https", _external=True), )
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 asNone
, no lower bound exists. Ifmax
is not specified, or is specified asNone
, no upper bound exists. The inclusivity of the bounds (if they exist) is configurable. Ifmin_inclusive
is not specified, or is specified asTrue
, then themin
bound is included in the range. Ifmax_inclusive
is not specified, or is specified asTrue
, then themax
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.
- 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 theSQLAlchemyAutoSchema
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 adb.Model
class fromflask_sqlalchemy
. Uses the scoped session from Flask-SQLAlchemy by default.See
marshmallow_sqlalchemy.SQLAlchemySchema
for more details on theSQLAlchemySchema
API.- OPTIONS_CLASS¶
alias of
SQLAlchemySchemaOpts
- opts: SchemaOpts = <flask_marshmallow.sqla.SQLAlchemySchemaOpts object>¶
- class flask_marshmallow.sqla.SQLAlchemySchemaOpts(meta, **kwargs)¶