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,
SQLAlchemySchemauses the scoped session created by Flask-SQLAlchemy.SQLAlchemySchemasubclassesflask_marshmallow.Schema, so it includes thejsonifymethod.
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
Schemaclass, 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.SQLAlchemySchemaandma.SQLAlchemyAutoSchema, which generate marshmallowSchemaclasses 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.Schemafor more details about theSchemaAPI.- 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
objshould be serialized as an instance or as a collection. If None, defaults to the value of themanyattribute 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
manyargument for this method defaults to the value of themanyattribute on the Schema. Previously, themanyargument 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
ValueErrorwill 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
datato 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
URLForobjects as values.Example:
_links = Hyperlinks( { "self": URLFor("author", values=dict(id="<id>")), "collection": URLFor("author_list"), } )
URLForobjects 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_forfunction, except that arguments can be pulled from the object to be serialized, and**valuesshould be passed to thevaluesparameter.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
minis not specified, or is specified asNone, no lower bound exists. Ifmaxis not specified, or is specified asNone, no upper bound exists. The inclusivity of the bounds (if they exist) is configurable. Ifmin_inclusiveis not specified, or is specified asTrue, then theminbound is included in the range. Ifmax_inclusiveis not specified, or is specified asTrue, then themaxbound 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
minbound is included in the range.max_inclusive – Whether the
maxbound 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.SQLAlchemyAutoSchemafor more details on theSQLAlchemyAutoSchemaAPI.- 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
modelclass Meta option, which should be adb.Modelclass fromflask_sqlalchemy. Uses the scoped session from Flask-SQLAlchemy by default.See
marshmallow_sqlalchemy.SQLAlchemySchemafor more details on theSQLAlchemySchemaAPI.- OPTIONS_CLASS¶
alias of
SQLAlchemySchemaOpts
- opts: SchemaOpts = <flask_marshmallow.sqla.SQLAlchemySchemaOpts object>¶
- class flask_marshmallow.sqla.SQLAlchemySchemaOpts(meta, **kwargs)¶