Package: unrest
UnRest - Simple sqlalchemy rest api generation.fromunrestimportUnRest# First, initialize UnRest with your web applicationrest=UnRest(app)# Then declare your endpointrest(Person)This should provide you a/api/personand 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.allYou will get both routes (collection and member) on the five methods. Please seethe wikipedia pagefor their signification.You can also override the default methods like this:person=rest(Person)@person.declare('GET')defget(payload,login=None):# Pre get hookiflogin:login=login.upper()rv=person.get(payload,login=login)# Post get hookreturn{'occurences':rv['occurences'],'objects':[{'login':person['login'].lower()}forpersoninrv['objects']]}DocumentationFull documentation can be found atkozea.github.io/unrestExampleConsider this simple web application:fromdatetimeimporttimedeltafromflaskimportFlaskfromflask_sqlalchemyimportSQLAlchemyfromsqlalchemy.ormimportrelationshipfromsqlalchemy.sql.schemaimportColumn,ForeignKeyfromsqlalchemy.typesimportInteger,Interval,Numeric,StringfromunrestimportUnRest# Flask applicationapp=Flask(__name__)app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=Falseapp.config['SQLALCHEMY_DATABASE_URI']='sqlite:////tmp/unrest.db'# Model definitiondb=SQLAlchemy(app)classTree(db.Model):id=Column(Integer,primary_key=True)name=Column(String)@propertydeffruit_colors(self):return', '.join([fruit.colorforfruitinself.fruits])classFruit(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 casedb.drop_all()# Create modeldb.create_all()# Data insertionpine=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 endpointsrest=UnRest(app,db.session)# Authorize every methodsrest(Tree,methods=rest.all,allow_batch=True)# Don't authorize batch for fruitsrest(Fruit,methods=rest.all)# Run the appapp.run(debug=True)You will now have:GETWith primary keys arguments$curl-shttp://localhost:5000/api/tree/1200OK{"occurences":1,"objects":[{"id":1,"name":"pine"}]}$curl-shttp://localhost:5000/api/fruit/1200OK{"occurences":1,"objects":[{"fruit_id":1,"color":"grey","size":12.0,"age":1041300.0,"tree_id":1}]}Without argument$curl-shttp://localhost:5000/api/tree200OK{"occurences":3,"objects":[{"id":1,"name":"pine"},{"id":2,"name":"maple"},{"id":3,"name":"oak"}]}$curl-shttp://localhost:5000/api/fruit200OK{"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}]}PUTWith primary keys arguments$curl-shttp://localhost:5000/api/tree/1 -X PUT -H "Content-Type: application/json" -d '{"name":"cedar"}'200OK{"occurences":1,"objects":[{"id":1,"name":"cedar"}]}Get it again to be sure:$curl-shttp://localhost:5000/api/tree/1200OK{"occurences":1,"objects":[{"id":1,"name":"cedar"}]}Without argument$curl-shttp://localhost:5000/api/tree -X PUT -H "Content-Type: application/json" -d '{"objects":[{"id":2,"name":"cedar"},{"id":22,"name":"mango"}]}'200OK{"occurences":2,"objects":[{"id":2,"name":"cedar"},{"id":22,"name":"mango"}]}Get it again to be sure:$curl-shttp://localhost:5000/api/tree200OK{"occurences":2,"objects":[{"id":2,"name":"cedar"},{"id":22,"name":"mango"}]}Check that whenallow_batchis not set we can't put all:$curl-shttp://localhost:5000/api/fruit -X PUT -H "Content-Type: application/json" -d '{"objects":[{"fruit_id":2,"color":"red"},{"fruit_id":22,"color":"blue"}]}'406NotAcceptable{"message":"You must set allow_batch to True if you want to use batch methods."}POSTWith primary keys arguments$curl-shttp://localhost:5000/api/tree/1 -X POST -H "Content-Type: application/json"501NotImplemented{"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-shttp://localhost:5000/api/fruit -X POST -H "Content-Type: application/json" -d '{"color":"forestgreen","size":3.14,"age":1.5926,"tree_id":3}'200OK{"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-shttp://localhost:5000/api/fruit200OK{"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}]}DELETEWith primary keys arguments$curl-shttp://localhost:5000/api/fruit/3 -X DELETE200OK{"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-shttp://localhost:5000/api/fruit200OK{"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 argumentBatch delete is not allowed on fruit:$curl-shttp://localhost:5000/api/fruit -X DELETE501NotImplemented{"message":"You must set allow_batch to True if you want to use batch methods."}But is on tree:$curl-shttp://localhost:5000/api/tree -X DELETE200OK{"occurences":3,"objects":[{"id":1,"name":"pine"},{"id":2,"name":"maple"},{"id":3,"name":"oak"}]}$curl-shttp://localhost:5000/api/tree200OK{"occurences":0,"objects":[]}PATCHWith primary keys arguments$curl-shttp://localhost:5000/api/fruit/1 -X PATCH -H "Content-Type: application/json" -d '{"color":"blue"}'200OK{"occurences":1,"objects":[{"fruit_id":1,"color":"blue","size":12.0,"age":1041300.0,"tree_id":1}]}Without argument$curl-shttp://localhost:5000/api/tree -X PATCH -H "Content-Type: application/json" -d '{"objects":[{"id":2,"name":"cedar"},{"id":3,"name":"mango"}]}'200OK{"occurences":2,"objects":[{"id":2,"name":"cedar"},{"id":3,"name":"mango"}]}Check that whenallow_batchis not set we can't put all:$curl-shttp://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}]}'406NotAcceptable{"message":"You must set allow_batch to True if you want to use batch methods."}otherwise all the specified attributes would have been patched.