A troubling rest api library for sqlalchemy models
Project description
UnRest - Simple sqlalchemy rest api generation.
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.
Source Distribution
Built Distribution
File details
Details for the file unrest-1.1.0.tar.gz
.
File metadata
- Download URL: unrest-1.1.0.tar.gz
- Upload date:
- Size: 43.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.25.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | be0417c08b0675698641258ab5f1e921c71ba8d6c3b54283566ebec7a7762164 |
|
MD5 | c730d113d980ba52e3e1f02771c5dff3 |
|
BLAKE2b-256 | d9fc0b9ce1c8018752824c2d72f3988f190cf07d1d53527e9c6811ce7e7e9374 |
File details
Details for the file unrest-1.1.0-py3-none-any.whl
.
File metadata
- Download URL: unrest-1.1.0-py3-none-any.whl
- Upload date:
- Size: 57.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.25.1
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0c2ee6294f4f3d7c94c01aa3f56c51ad70e8a8e5f68b6efdcc37d185360efbf6 |
|
MD5 | ec28007b9cc40a0ef42e3538338a7d13 |
|
BLAKE2b-256 | 824c66f47280d043b8700541de96d4c170eb147eeb9c5cd59e0c46a9839ae0c5 |