Flask-jsonapi¶
JSONAPI 1.0 server implementation for Flask.
Flask-jsonapi is a server implementation of JSON API 1.0 specification for Flask. It allows for rapid creation of CRUD JSON API endpoints. Those endpoints can be used by JSON API clients, eg. JavaScript frontend applications written in Ember.js, React, Angular.js etc.
A compatible Python client can be found in the following package: jsonapi-request.
Flask-jsonapi depends on the following external libraries:
- Flask (micro web framework)
- marshmallow-jsonapi (serialization, deserialization, validation with JSON API format)
- SQLAlchemy (SQL ORM)
Features¶
Flask-jsonapi implements the following parts of the JSON API specification:
- fetching resources [specification]
- creating, updating and deleting resources [specification]
- inclusion of related resources [specification]
- filtering - helps with adding filters to views (including helpers for SQLAlchemy), the format is compatible with recommendations
- sorting [specification]
- pagination [specification]
- sparse fieldsets [specification]
- links [specification] - resolved by marshmallow-jsonapi (docs)
- error objects [specification]
- resource-level permissions - view-level decorators support in ViewSets
- object-level permissions - interfaces added in [#43]
Not implemented yet:
- fetching relationships [specification] and updating relationships [specification] - #27
Architecture¶
Flow through layers beginning with an HTTP Request and ending with an HTTP Response:
Schema
🡙
[HTTP Request] -> [Flask Routing] -> ViewSet -> View -> Repository -> ( )
( Storage )
[HTTP Response] <- View <- Repository <- ( )
🡙
Schema
Simple example¶
Let’s create a working example of a minimal Flask application. It will expose a single resource Article
as
a REST endpoint with fetch/create/update/delete operations. For persistence layer, it will use an in-memory SQLite
database with SQLAlchemy for storage.
Configuration¶
import flask
import sqlalchemy
from sqlalchemy.orm import scoped_session
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from marshmallow_jsonapi import Schema, fields
import flask_jsonapi
from flask_jsonapi.resource_repositories import sqlalchemy_repositories
db_engine = sqlalchemy.create_engine('sqlite:///')
session = scoped_session(sessionmaker(bind=db_engine))
Base = declarative_base()
Base.query = session.query_property()
class Article(Base):
__tablename__ = 'articles'
id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
title = sqlalchemy.Column(sqlalchemy.String)
Base.metadata.create_all(db_engine)
class ArticleRepository(sqlalchemy_repositories.SqlAlchemyModelRepository):
model = Article
instance_name = 'articles'
session = session
class ArticleSchema(Schema):
id = fields.Int()
title = fields.Str()
class Meta:
type_ = 'articles'
strict = True
class ArticleRepositoryViewSet(flask_jsonapi.resource_repository_views.ResourceRepositoryViewSet):
schema = ArticleSchema
repository = ArticleRepository()
app = flask.Flask(__name__)
api = flask_jsonapi.Api(app)
api.repository(ArticleRepositoryViewSet(), 'articles', '/articles/')
app.run(host='127.0.0.1', port=5000)
Usage¶
Create a new Article
with title “First article”:
curl -H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
http://localhost:5000/articles/ \
--data '{"data": {"attributes": {"title": "First article"}, "type": "articles"}}' \
2>/dev/null | python -m json.tool
Result:
{
"data": {
"type": "articles",
"id": 1,
"attributes": {
"title": "First article"
}
},
"jsonapi": {
"version": "1.0"
}
}
Get the list of Articles
:
curl -H 'Accept: application/vnd.api+json' \
http://localhost:5000/articles/ \
2>/dev/null | python -m json.tool
Result:
{
"data": [
{
"type": "articles",
"id": 1,
"attributes": {
"title": "First article"
}
}
],
"jsonapi": {
"version": "1.0"
},
"meta": {
"count": 1
}
}