Build REST APIs with Neo4j and Flask, as quickly as possible!
gREST (Graph-based REST API Framework) is a RESTful API development framework on top of Python, Flask, Neo4j and Neomodel. Its primary purpose is to ease development of RESTful APIs with little effort and minimum amount of code.
This package is not maintained regularly and there might be many issues, which is due to the constraints on my time and interest to contribute to its development. The original idea was to devise a simple way to store and traverse graph-based data and to create REST APIs on top of Flask and Neo4j. Today, there are many standard industry-proven technologies such as GraphQL that can do the job much better than gREST. Still, I'd be happy to help you if you have issues.
If you want to use gREST with Python 2.7, you will need to stick with the good old 1.4.0 version. For Python 3.x onwards, use the latest version starting with 2.x.x or the master
branch.
If you're using gREST on your project, please let me know on Twitter or open an issue.
- Supported HTTP verbs:
GET
,POST
,PUT
,PATCH
,DELETE
- Supported response serialization methods (based on accept header): JSON, XML, YAML
- Indexing with skip/limit and order support
- Helper functions for handling of nodes and relations
- Simple configuration management
- Automatic validation of input data (plus monkey-patching of manual validation rules)
- Deep relationship support between nodes: /primary_model/primary_model_item/related_model/related_model_item
- Support for getting/posting relationship data between nodes
- Support for user-defined authentication and authorization
- Support for unicode routes (e.g. unicode tags)
To install gREST, you can use setuptools (install from source) or use a python package manager (e.g. pip or easy_install).
- To install from
source code
, clone the repository (you should have git installed) and then run setup.py:
$ git clone https://github.com/mostafa/grest.git
$ cd grest
$ python setup.py install
- To install using a python package manager via
binary package
, simply run this command (in this case we've used pip, but any package manager is accepted as long as it uses PyPI):
$ pip install pygrest
$ cd path/to/project
$ pip install -e .
For detailed documentation, please visit http://grest.readthedocs.io/.
You can find an example app in examples directory.
app.py
is a simple grest app that contains only one route(/persons)
.extended_app.py
is the extended version of the above app and contains another route(/pets)
, its relationship withPerson
model and a custom method (route) to handleRelationshipFrom
properties. TheRelationshipTo
is automatically constructed using secondary model and secondary selection field of thePersonsView
.
The package ships a very simple command that can help you create a boilerplate Flask application. Simply run the following command:
grest <project_name>
In order to build an API, you should make a simple Flask app (or you may already have one).
A simple Flask app:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run(debug=True, threaded=True)
To use gREST, you should define your models with Neomodel syntax. Neomodel is easier to use than other ORMs and drivers. Take a look at this example:
from neomodel import (StructuredNode, UniqueIdProperty, StringProperty)
from grest import models
class Person(StructuredNode, models.Node):
uid = UniqueIdProperty()
first_name = StringProperty()
last_name = StringProperty()
As you can see, we have imported models
from grest
, so that we can use the Node
mixin (which is used in JSON serialization of model data). Also note that the Person
class (model) is inheriting from two parents: StructuredNode
and Node
.
Then we should inherit from grest
to make a new view of our model (so that it accepts RESTful verbs):
from grest import GRest
class PersonsView(GRest):
__model__ = {"primary": Person}
__selection_field__ = {"primary": "uid"}
The most important part of grest is __model__
and __selection_field__
properties. They contain the logic to access your models and relations. As you see, our primary
model is Person
and its primary key (so to say) is uid
, so the selection field of the primary model is uid
.
You should register this view:
PersonsView.register(app, route_base="/persons", trailing_slash=False)
User input should never be trusted, so input validation is done by using webargs:
To include input validation in each model, you should include __validation_rules__
property, which is a mapping dictionary of keys (models' fields) and values (data type and validation rules).
__validation_rules__
property is there for customization of validation rules, with the release of version 0.2.1, validation rules are inferred and constructred from your models' properties, so it is unnecessary to define it in most cases.
from neomodel import (StructuredNode, UniqueIdProperty, StringProperty)
from grest import models
from webargs import fields
class Person(StructuredNode, models.Node):
__validation_rules__ = {
"uid": fields.Str(),
"first_name": fields.Str(),
"last_name": fields.Str()
}
uid = UniqueIdProperty()
first_name = StringProperty()
last_name = StringProperty()
You can override default behavior of HTTP verbs (index, get, post, put, patch and delete) and also make custom endpoints under this PersonsView
class.
Last but not least, you should set up your app's connection to the database (Neo4j), which is done by setting the DATABASE_URL
propery of neomodel.config
:
neomodel.config.DATABASE_URL = "bolt://neo4j:neo4j@localhost:7687"
One last part is to connect the logger of grest to Flask, or use a custom logger:
app.ext_logger = app.logger
app.ext_logger
is the variable grest looks for, to log messages.
You can run this app either in development or production environments:
As it is the same flask application, you can run it in development like this:
$ python app.py
For production purposes, you can use docker using tiangolo/uwsgi-nginx-flask:python2.7
image or use your own setup.
Contribution is always welcome! To report bugs, simply open an issue and fill it with related information. To fix a bug, fork the repository, fix the bug, push to your own fork, make a pull request and done!