JSON API tools for Flask
Project description
Flask JsonTools
JSON API tools for Flask
Table of Contents
View Utilities
@jsonapi
JsonResponse
make_json_response()
FlaskJsonClient
Class-Based Views
MethodView
RestfulView
View Utilities
@jsonapi
Decorate a view function that talks JSON.
Such function can return:
tuples of (response, status[, headers]): to set custom status code and optionally - headers
Instances of `JsonResponse <#jsonresponse>`__
The result of helper function `make_json_response <#make_json_response>`__
Example:
from flask.ext.jsontools import jsonapi
@app.route('/users')
@jsonapi
def list_users():
return [
{'id': 1, 'login': 'kolypto'},
#...
]
@app.route('/user/<int:id>', methods=['DELETE'])
def delete_user(id):
return {'error': 'Access denied'}, 403
JsonResponse
Extends `flask.Request <http://flask.pocoo.org/docs/api/#incoming-request-data>`__ and encodes the response with JSON. Views decorated with `@jsonapi <#jsonapi>`__ return these objects.
Arguments:
response: response data
status: status code. Optional, defaults to 200
headers: additional headers dict. Optional.
**kwargs: additional argumets for `Response <http://flask.pocoo.org/docs/api/#response-objects>`__
Methods:
preprocess_response_data(response): Override to get custom response behavior.
get_json(): Get the original response data.
__getitem__(key): Get an item from the response data
The extra methods allows to reuse views:
from flask.ext.jsontools import jsonapi
@app.route('/user', methods=['GET'])
@jsonapi
def list_users():
return [ { 1: 'first', 2: 'second' } ]
@app.route('/user/<int:id>', methods=['GET'])
@jsonapi
def get_user(id):
return list_users().get_json()[id] # Long form
return list_users()[id] # Shortcut
make_json_response()
Helper function that actually preprocesses view return value into `JsonResponse <#jsonresponse>`__.
Accepts rv as any of:
tuple of (response, status[, headers])
Object to encode as JSON
FlaskJsonClient
FlaskJsonClient is a JSON-aware test client: it can post JSON and parse JSON responses into `JsonResponse <#jsonresponse>`__.
from myapplication import Application
from flask.ext.jsontools import FlaskJsonClient
def JsonTest(unittest.TestCase):
def setUp(self):
self.app = Application(__name__)
self.app.test_client_class = FlaskJsonClient
def testCreateUser(self):
with self.app.test_client() as c:
rv = c.post('/user/', json={'name': 'kolypto'})
# rv is JsonResponse
rv.status_code
rv.get_json()['user'] # Long form for the previous
rv['user'] # Shortcut for the previous
Formatting Utils
DynamicJSONEncoder
In python, de-facto standard for encoding objects of custom classes is the __json__() method which returns the representation of the object.
DynamicJSONEncoder is the implementation of this protocol: if an object has the __json__() method, its result if used for the representation.
You’ll definitely want to subclass it to support other types, e.g. dates and times:
from flask.ext.jsontools import DynamicJSONEncoder
class ApiJSONEncoder(DynamicJSONEncoder):
def default(self, o):
# Custom formats
if isinstance(o, datetime.datetime):
return o.isoformat(' ')
if isinstance(o, datetime.date):
return o.isoformat()
if isinstance(o, set):
return list(o)
# Fallback
return super(DynamicJSONEncoder, self).default(o)
Now, just install the encoder to your Flask:
from flask import Flask
app = Flask(__name__)
app.json_encoder = DynamicJSONEncoder
JsonSerializableBase
Serializing SqlAlchemy models to JSON is a headache: if an attribute is present on an instance, this does not mean it’s loaded from the database.
JsonSerializableBase is a mixin for SqlAlchemy Declarative Base that adds a magic __json__() method, compatible with `DynamicJSONEncoder <#dynamicjsonencoder>`__. When serializing, it makes sure that entity serialization will never issue additional requests.
Example:
from sqlalchemy.ext.declarative import declarative_base
from flask.ext.jsontools import JsonSerializableBase
Base = declarative_base(cls=(JsonSerializableBase,))
class User(Base):
#...
Now, you can safely respond with SqlAlchemy models in your JSON views, and jsontools will handle the rest :)
Class-Based Views
Module flask.ext.jsontools.views contains a couple of classes that allow to build class-based views which dispatch to different methods.
In contrast to MethodView, this gives much higher flexibility.
MethodView
Using MethodView class for methods, decorate them with @methodview(), which takes the following arguments:
methods=(): Iterable of HTTP methods to use with this method.
ifnset=None: Conditional matching. List of route parameter names that should not be set for this method to match.
ifset=None: Conditional matching. List of route parameter names that should be set for this method to match.
This allows to map HTTP methods to class methods, and in addition define when individual methods should match.
Quick example:
from flask.ext.jsontools import jsonapi, MethodView, methodview
class UserView(MethodView):
# Canonical way to specify decorators for class-based views
decorators = (jsonapi, )
@methodview
def list(self):
""" List users """
return db.query(User).all()
@methodview
def get(self, user_id):
""" Load a user by id """
return db.query(User).get(user_id)
userview = CrudView.as_view('user')
app.add_url_rule('/user/', view_func=userview)
app.add_url_rule('/user/<int:user_id>', view_func=userview)
Now, GET HTTP method is routed to two different methods depending on conditions. Keep defining more methods to get good routing :)
To simplify the last step of creating the view, there’s a helper:
UserView.route_as_view(app, 'user', ('/user/', '/user/<int:user_id>'))
RestfulView
Since MethodView is mostly useful to expose APIs over collections of entities, there is a RESTful helper which automatically decorates some special methods with @methodview.
View method |
HTTP method |
URL |
---|---|---|
list() |
GET |
/ |
create() |
POST |
/ |
get() |
GET |
/<pk> |
replace() |
PUT |
/<pk> |
update() |
POST |
/<pk> |
delete() |
DELETE |
/<pk> |
By subclassing RestfulView and implementing some of these methods, you’ll get a complete API endpoint with a single class.
It’s also required to define the list of primary key fields by defining the primary_key property:
from flask.ext.jsontools import jsonapi, RestfulView
class User(RestfulView):
decorators = (jsonapi, )
primary_key = ('id',)
#region Operation on the collection
def list():
return db.query(User).all()
def create():
db.save(user)
return user
#endregion
#region Operation on entities
def get(id):
return db.query(User).get(id)
def replace(id):
db.save(user, id)
def update(id):
db.save(user)
def delete(id):
db.delete(user)
#endregion
When a class like this is defined, its metaclass goes through the methods and decorates them with @methodview. This way, list() gets @methodview('GET', ifnset=('id',)), and get() gets @methodview('GET', ifset=('id',)).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file flask_jsontools_slippers-0.1.6.tar.gz
.
File metadata
- Download URL: flask_jsontools_slippers-0.1.6.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 63717b875c7159ca4de6aec31bf203ccf8137edaaf0e5851f61093bfb231057b |
|
MD5 | fff1744de8106955cba1123e4e75897a |
|
BLAKE2b-256 | 3ba7154125c246c593bf4f6788a226fc82d1f45573c81a5130d5ae40376b05c8 |
File details
Details for the file flask_jsontools_slippers-0.1.6-py2.py3-none-any.whl
.
File metadata
- Download URL: flask_jsontools_slippers-0.1.6-py2.py3-none-any.whl
- Upload date:
- Size: 20.5 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1a538418ebcaa0b2140a7eadae982158db92f84aec49dc2f48f5fb7533bd69f1 |
|
MD5 | 624d6da47fb8895f70a40060b782e25e |
|
BLAKE2b-256 | 6c1d12f5448d3543ab0dd0e90428aa6f8164ef79996a0e543ef7c4cc00bfd487 |