1********************************************************* 2Flask-Marshmallow: Flask + marshmallow for beautiful APIs 3********************************************************* 4 5:ref:`changelog <changelog>` // 6`github <http://github.com/marshmallow-code/flask-marshmallow>`_ // 7`pypi <http://pypi.python.org/pypi/flask-marshmallow>`_ // 8`issues <http://github.com/marshmallow-code/flask-marshmallow/issues>`_ 9 10 11Flask + marshmallow for beautiful APIs 12====================================== 13 14Flask-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 <http://flask-sqlalchemy.pocoo.org/>`_. 15 16Get it now 17---------- 18:: 19 20 pip install flask-marshmallow 21 22 23Create your app. 24 25.. code-block:: python 26 27 from flask import Flask 28 from flask_marshmallow import Marshmallow 29 30 app = Flask(__name__) 31 ma = Marshmallow(app) 32 33Write your models. 34 35.. code-block:: python 36 37 from your_orm import Model, Column, Integer, String, DateTime 38 39 40 class User(Model): 41 email = Column(String) 42 password = Column(String) 43 date_created = Column(DateTime, auto_now_add=True) 44 45 46Define your output format with marshmallow. 47 48.. code-block:: python 49 50 51 class UserSchema(ma.Schema): 52 class Meta: 53 # Fields to expose 54 fields = ("email", "date_created", "_links") 55 56 # Smart hyperlinking 57 _links = ma.Hyperlinks( 58 { 59 "self": ma.URLFor("user_detail", values=dict(id="<id>")), 60 "collection": ma.URLFor("users"), 61 } 62 ) 63 64 65 user_schema = UserSchema() 66 users_schema = UserSchema(many=True) 67 68 69Output the data in your views. 70 71.. code-block:: python 72 73 @app.route("/api/users/") 74 def users(): 75 all_users = User.all() 76 return users_schema.dump(all_users) 77 78 79 @app.route("/api/users/<id>") 80 def user_detail(id): 81 user = User.get(id) 82 return user_schema.dump(user) 83 84 85 # { 86 # "email": "fred@queen.com", 87 # "date_created": "Fri, 25 Apr 2014 06:02:56 -0000", 88 # "_links": { 89 # "self": "/api/users/42", 90 # "collection": "/api/users/" 91 # } 92 # } 93 94 95 96Optional Flask-SQLAlchemy Integration 97------------------------------------- 98 99Flask-Marshmallow includes useful extras for integrating with `Flask-SQLAlchemy <http://flask-sqlalchemy.pocoo.org/>`_ and `marshmallow-sqlalchemy <https://marshmallow-sqlalchemy.readthedocs.io>`_. 100 101To enable SQLAlchemy integration, make sure that both Flask-SQLAlchemy and marshmallow-sqlalchemy are installed. :: 102 103 pip install -U flask-sqlalchemy marshmallow-sqlalchemy 104 105Next, initialize the `~flask_sqlalchemy.SQLAlchemy` and `~flask_marshmallow.Marshmallow` extensions, in that order. 106 107.. code-block:: python 108 109 from flask import Flask 110 from flask_sqlalchemy import SQLAlchemy 111 from flask_marshmallow import Marshmallow 112 113 app = Flask(__name__) 114 app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db" 115 116 # Order matters: Initialize SQLAlchemy before Marshmallow 117 db = SQLAlchemy(app) 118 ma = Marshmallow(app) 119 120.. admonition:: Note on initialization order 121 122 Flask-SQLAlchemy **must** be initialized before Flask-Marshmallow. 123 124 125Declare your models like normal. 126 127 128.. code-block:: python 129 130 class Author(db.Model): 131 id = db.Column(db.Integer, primary_key=True) 132 name = db.Column(db.String(255)) 133 134 135 class Book(db.Model): 136 id = db.Column(db.Integer, primary_key=True) 137 title = db.Column(db.String(255)) 138 author_id = db.Column(db.Integer, db.ForeignKey("author.id")) 139 author = db.relationship("Author", backref="books") 140 141 142Generate marshmallow `Schemas <marshmallow.Schema>` from your models using `~flask_marshmallow.sqla.SQLAlchemySchema` or `~flask_marshmallow.sqla.SQLAlchemyAutoSchema`. 143 144.. code-block:: python 145 146 class AuthorSchema(ma.SQLAlchemySchema): 147 class Meta: 148 model = Author 149 150 id = ma.auto_field() 151 name = ma.auto_field() 152 books = ma.auto_field() 153 154 155 class BookSchema(ma.SQLAlchemyAutoSchema): 156 class Meta: 157 model = Book 158 include_fk = True 159 160You can now use your schema to dump and load your ORM objects. 161 162 163.. code-block:: python 164 165 db.create_all() 166 author_schema = AuthorSchema() 167 book_schema = BookSchema() 168 author = Author(name="Chuck Paluhniuk") 169 book = Book(title="Fight Club", author=author) 170 db.session.add(author) 171 db.session.add(book) 172 db.session.commit() 173 author_schema.dump(author) 174 # {'id': 1, 'name': 'Chuck Paluhniuk', 'books': [1]} 175 176 177`~flask_marshmallow.sqla.SQLAlchemySchema` is nearly identical in API to `marshmallow_sqlalchemy.SQLAlchemySchema` with the following exceptions: 178 179- By default, `~flask_marshmallow.sqla.SQLAlchemySchema` uses the scoped session created by Flask-SQLAlchemy. 180- `~flask_marshmallow.sqla.SQLAlchemySchema` subclasses `flask_marshmallow.Schema`, so it includes the `~flask_marshmallow.Schema.jsonify` method. 181Note: 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 <https://marshmallow.readthedocs.io/en/latest/quickstart.html#ordering-output>`_ 182in 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 `~flask_marshmallow.sqla.SQLAlchemySchema` in order to minimize generation time and maximize cacheability of the results. 183 184You can also use `ma.HyperlinkRelated <flask_marshmallow.sqla.HyperlinkRelated>` fields if you want relationships to be represented by hyperlinks rather than primary keys. 185 186 187.. code-block:: python 188 189 class BookSchema(ma.SQLAlchemyAutoSchema): 190 class Meta: 191 model = Book 192 193 author = ma.HyperlinkRelated("author_detail") 194 195.. code-block:: python 196 197 with app.test_request_context(): 198 print(book_schema.dump(book)) 199 # {'id': 1, 'title': 'Fight Club', 'author': '/authors/1'} 200 201The first argument to the `~flask_marshmallow.sqla.HyperlinkRelated` constructor is the name of the view used to generate the URL, just as you would pass it to the `~flask.url_for` function. If your models and views use the ``id`` attribute 202as a primary key, you're done; otherwise, you must specify the name of the 203attribute used as the primary key. 204 205To represent a one-to-many relationship, wrap the `~flask_marshmallow.sqla.HyperlinkRelated` instance in a `marshmallow.fields.List` field, like this: 206 207.. code-block:: python 208 209 class AuthorSchema(ma.SQLAlchemyAutoSchema): 210 class Meta: 211 model = Author 212 213 books = ma.List(ma.HyperlinkRelated("book_detail")) 214 215.. code-block:: python 216 217 with app.test_request_context(): 218 print(author_schema.dump(author)) 219 # {'id': 1, 'name': 'Chuck Paluhniuk', 'books': ['/books/1']} 220 221 222API 223=== 224 225.. automodule:: flask_marshmallow 226 :members: 227 228.. automodule:: flask_marshmallow.fields 229 :members: 230 231.. automodule:: flask_marshmallow.sqla 232 :members: 233 234 235Useful Links 236============ 237 238- `Flask docs`_ 239- `marshmallow docs`_ 240 241.. _marshmallow docs: http://marshmallow.readthedocs.io 242 243.. _Flask docs: http://flask.pocoo.org/docs/ 244 245Project Info 246============ 247 248.. toctree:: 249 :maxdepth: 1 250 251 license 252 changelog 253 254 255.. _marshmallow: http://marshmallow.readthedocs.io 256 257 .. _Flask: http://flask.pocoo.org 258