A troubling rest api library for sqlalchemy models
Project description
UnRest - <small>Simple sqlalchemy rest api generation.</small>
from unrest import UnRest # First, initialize UnRest with your web application rest = UnRest(app) # Then declare your endpoint rest(Person)
This should provide you a /api/person
and a /api/person/<login>
route accessible in GET only.
To activate data modification, set the methods array like this:
rest(Person, only=['name', 'sex', 'age'], methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH']) # or simply methods=rest.all
You will get both routes (collection and member) on the five methods. Please see the wikipedia page for their signification.
You can also override the default methods like this:
person = rest(Person) @person.declare('GET') def get(payload, login=None): # Pre get hook if login: login = login.upper() rv = person.get(payload, login=login) # Post get hook return { 'occurences': rv['occurences'], 'objects': [ {'login': person['login'].lower()} for person in rv['objects'] ] }
Documentation
Full documentation can be found at kozea.github.io/unrest
Example
Consider this simple web application:
from datetime import timedelta from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm import relationship from sqlalchemy.sql.schema import Column, ForeignKey from sqlalchemy.types import Integer, Interval, Numeric, String from unrest import UnRest # Flask application app = Flask(__name__) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/unrest.db' # Model definition db = SQLAlchemy(app) class Tree(db.Model): id = Column(Integer, primary_key=True) name = Column(String) @property def fruit_colors(self): return ', '.join([fruit.color for fruit in self.fruits]) class Fruit(db.Model): fruit_id = Column(Integer, primary_key=True) color = Column(String(50)) size = Column(Numeric) age = Column(Interval) tree_id = Column(Integer, ForeignKey('tree.id')) tree = relationship(Tree, backref='fruits') # Drop everything just in case db.drop_all() # Create model db.create_all() # Data insertion pine = Tree(name='pine') maple = Tree(name='maple') oak = Tree(name='oak') db.session.add(pine) db.session.add(maple) db.session.add(oak) db.session.add(Fruit(color='grey', size=12, age=timedelta(days=12, hours=1, minutes=15), tree=pine)) db.session.add(Fruit(color='darkgrey', size=23, age=timedelta(days=49, seconds=230, milliseconds=213), tree=pine)) db.session.add(Fruit(color='brown', size=2.12, age=timedelta(0), tree=pine)) db.session.add(Fruit(color='red', size=.5, age=timedelta(minutes=40), tree=maple)) db.session.add(Fruit(color='orangered', size=100, age=timedelta(hours=2, microseconds=12), tree=maple)) db.session.commit() db.session.remove() # Declare rest endpoints rest = UnRest(app, db.session) # Authorize every methods rest(Tree, methods=rest.all, allow_batch=True) # Don't authorize batch for fruits rest(Fruit, methods=rest.all) # Run the app app.run(debug=True)
You will now have:
GET
With primary keys arguments
$ curl -s http://localhost:5000/api/tree/1 200 OK { "occurences": 1, "objects": [ { "id": 1, "name": "pine" } ] }
$ curl -s http://localhost:5000/api/fruit/1 200 OK { "occurences": 1, "objects": [ { "fruit_id": 1, "color": "grey", "size": 12.0, "age": 1041300.0, "tree_id": 1 } ] }
Without argument
$ curl -s http://localhost:5000/api/tree 200 OK { "occurences": 3, "objects": [ { "id": 1, "name": "pine" }, { "id": 2, "name": "maple" }, { "id": 3, "name": "oak" } ] }
$ curl -s http://localhost:5000/api/fruit 200 OK { "occurences": 5, "objects": [ { "fruit_id": 1, "color": "grey", "size": 12.0, "age": 1041300.0, "tree_id": 1 }, { "fruit_id": 2, "color": "darkgrey", "size": 23.0, "age": 4233830.213, "tree_id": 1 }, { "fruit_id": 3, "color": "brown", "size": 2.12, "age": 0.0, "tree_id": 1 }, { "fruit_id": 4, "color": "red", "size": 0.5, "age": 2400.0, "tree_id": 2 }, { "fruit_id": 5, "color": "orangered", "size": 100.0, "age": 7200.000012, "tree_id": 2 } ] }
PUT
With primary keys arguments
$ curl -s http://localhost:5000/api/tree/1 -X PUT -H "Content-Type: application/json" -d '{ "name": "cedar" }' 200 OK { "occurences": 1, "objects": [ { "id": 1, "name": "cedar" } ] }
Get it again to be sure:
$ curl -s http://localhost:5000/api/tree/1 200 OK { "occurences": 1, "objects": [ { "id": 1, "name": "cedar" } ] }
Without argument
$ curl -s http://localhost:5000/api/tree -X PUT -H "Content-Type: application/json" -d '{ "objects": [{"id": 2, "name": "cedar"}, {"id": 22, "name": "mango"}] }' 200 OK { "occurences": 2, "objects": [ { "id": 2, "name": "cedar" }, { "id": 22, "name": "mango" } ] }
Get it again to be sure:
$ curl -s http://localhost:5000/api/tree 200 OK { "occurences": 2, "objects": [ { "id": 2, "name": "cedar" }, { "id": 22, "name": "mango" } ] }
Check that when allow_batch
is not set we can't put all:
$ curl -s http://localhost:5000/api/fruit -X PUT -H "Content-Type: application/json" -d '{ "objects": [ {"fruit_id": 2, "color": "red"}, {"fruit_id": 22, "color": "blue"} ] }' 406 Not Acceptable { "message": "You must set allow_batch to True if you want to use batch methods." }
POST
With primary keys arguments
$ curl -s http://localhost:5000/api/tree/1 -X POST -H "Content-Type: application/json" 501 Not Implemented { "message": "POST on id corresponds to collection creation. It's not implemented by default. If you want to update an item use the PUT method instead" }
Without argument
$ curl -s http://localhost:5000/api/fruit -X POST -H "Content-Type: application/json" -d '{ "color": "forestgreen", "size": 3.14, "age": 1.5926, "tree_id": 3 }' 200 OK { "occurences": 1, "objects": [ { "fruit_id": 6, "color": "forestgreen", "size": 3.14, "age": 1.5926, "tree_id": 3 } ] }
Now we should have a total of 6 fruits:
$ curl -s http://localhost:5000/api/fruit 200 OK { "occurences": 6, "objects": [ { "fruit_id": 1, "color": "grey", "size": 12.0, "age": 1041300.0, "tree_id": 1 }, { "fruit_id": 2, "color": "darkgrey", "size": 23.0, "age": 4233830.213, "tree_id": 1 }, { "fruit_id": 3, "color": "brown", "size": 2.12, "age": 0.0, "tree_id": 1 }, { "fruit_id": 4, "color": "red", "size": 0.5, "age": 2400.0, "tree_id": 2 }, { "fruit_id": 5, "color": "orangered", "size": 100.0, "age": 7200.000012, "tree_id": 2 }, { "fruit_id": 6, "color": "forestgreen", "size": 3.14, "age": 1.5926, "tree_id": 3 } ] }
DELETE
With primary keys arguments
$ curl -s http://localhost:5000/api/fruit/3 -X DELETE 200 OK { "occurences": 1, "objects": [ { "fruit_id": 3, "color": "brown", "size": 2.12, "age": 0.0, "tree_id": 1 } ] }
Now we should have only 5 fruits remaining:
$ curl -s http://localhost:5000/api/fruit 200 OK { "occurences": 5, "objects": [ { "fruit_id": 1, "color": "grey", "size": 12.0, "age": 1041300.0, "tree_id": 1 }, { "fruit_id": 2, "color": "darkgrey", "size": 23.0, "age": 4233830.213, "tree_id": 1 }, { "fruit_id": 4, "color": "red", "size": 0.5, "age": 2400.0, "tree_id": 2 }, { "fruit_id": 5, "color": "orangered", "size": 100.0, "age": 7200.000012, "tree_id": 2 }, { "fruit_id": 6, "color": "forestgreen", "size": 3.14, "age": 1.5926, "tree_id": 3 } ] }
Without argument
Batch delete is not allowed on fruit:
$ curl -s http://localhost:5000/api/fruit -X DELETE 501 Not Implemented { "message": "You must set allow_batch to True if you want to use batch methods." }
But is on tree:
$ curl -s http://localhost:5000/api/tree -X DELETE 200 OK { "occurences": 3, "objects": [ { "id": 1, "name": "pine" }, { "id": 2, "name": "maple" }, { "id": 3, "name": "oak" } ] }
$ curl -s http://localhost:5000/api/tree 200 OK { "occurences": 0, "objects": [] }
PATCH
With primary keys arguments
$ curl -s http://localhost:5000/api/fruit/1 -X PATCH -H "Content-Type: application/json" -d '{ "color": "blue" }' 200 OK { "occurences": 1, "objects": [ { "fruit_id": 1, "color": "blue", "size": 12.0, "age": 1041300.0, "tree_id": 1 } ] }
Without argument
$ curl -s http://localhost:5000/api/tree -X PATCH -H "Content-Type: application/json" -d '{ "objects": [{"id": 2, "name": "cedar"}, {"id": 3, "name": "mango"}] }' 200 OK { "occurences": 2, "objects": [ { "id": 2, "name": "cedar" }, { "id": 3, "name": "mango" } ] }
Check that when allow_batch
is not set we can't put all:
$ curl -s http://localhost:5000/api/fruit -X PATCH -H "Content-Type: application/json" -d '{ "objects": [ {"fruit_id": 1, "color": "blue"}, {"fruit_id": 3, "age": 1038540.0}, {"fruit_id": 4, "color": "rainbow", "size": 8}, {"fruit_id": 5, "size": 10, "tree_id": 1} ] }' 406 Not Acceptable { "message": "You must set allow_batch to True if you want to use batch methods." }
otherwise all the specified attributes would have been patched.
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.