Last active
October 25, 2023 13:21
-
-
Save aanastasiou/8e2ffdf9a5dd87954e013ff99ef92f91 to your computer and use it in GitHub Desktop.
Using neomodel with Flask
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import neomodel | |
class Item(neomodel.StructuredNode): | |
__primarykey__ = "name" | |
name = neomodel.StringProperty(unique_index=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
A simple example showing how using neomodel with Flask in a naive way | |
can lead to exceptions. | |
This example is based on code found in this stack-overflow post: | |
https://stackoverflow.com/questions/52877575/flask-and-neomodel-modeldefinitionmismatch | |
!!! WARNING !!! | |
* Prior to running this example, please make sure that the NEO4J_BOLT_URL environment | |
variable, points to a working and properly setup instance of a neo4j dbms. | |
///FOLLOW THE CODE LINE-TO-LINE TO GET A COHERENT NARRATIVE FROM THE INLINE COMMENTS/// | |
""" | |
import os | |
import json | |
import flask | |
import neomodel | |
class Item(neomodel.StructuredNode): | |
__primarykey__ = 'name' | |
name = neomodel.StringProperty(unique_index=True) | |
def create_an_item(): | |
neomodel.db.set_connection(os.environ['NEO4J_BOLT_URL']) | |
Item(name='Something Something Dark Side').save() | |
def create_app(): | |
""" | |
This is the original way presented to create a class. Please note | |
the inline comments throughout | |
""" | |
# In this example a Flask application is created explicity. | |
app = flask.Flask(__name__) | |
neomodel.config.DATABASE_URL = os.environ['NEO4J_BOLT_URL'] | |
# At this point, the neomodel.db object has been initialised as expected | |
@app.route('/', methods=['GET']) | |
def get_all_items(): | |
# At the time this function gets to be called, it operates in a different | |
# process and therefore the neomodel.db that is used implicitly in retrieving | |
# the Item from the database is completely different than the neomodel.db that | |
# that was initialised in the process of execution that created the app object. | |
# Anything running within the request serving functions is entirely independent stand-alone code. | |
return flask.jsonify({'items': [item.name for item in Item.nodes]}) | |
return app | |
if __name__ == '__main__': | |
# !!!PRIOR TO RUNNING THE APP, CREATE AT LEAST ONE Item IN THE DATABASE!!! | |
create_an_item() | |
# Comment the above line and uncomment the following two to launch the app | |
# flask_app = create_app() | |
# At this point, the neomodel.db object used in this process is configured and valid | |
# flask_app.run() | |
# At this point, the neomodel.db object stays configured and valid | |
# IN THIS THREAD OF EXECUTION | |
# | |
# For every subsequent request, a completely new process | |
# is created. The neomodel.db object within THAT thread of execution | |
# would not have undergone the kind of preparation it has for this | |
# process. Consequently, its _NODE_CLASS_REGISTRY would be empty | |
# and any attempt to instantiate objects from the app's model would | |
# fail. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Continuing from the above example, here is the _naive_ way of fixing the problem. | |
What is different in this script is the way that the neomodel.db object is being managed. | |
!!! WARNING !!! | |
* Prior to running this example, please make sure that the NEO4J_BOLT_URL environment | |
variable, points to a working and properly setup instance of a neo4j dbms. | |
///FOLLOW THE CODE LINE-TO-LINE TO GET A COHERENT NARRATIVE FROM THE INLINE COMMENTS/// | |
""" | |
import os | |
import json | |
import flask | |
import neomodel | |
# !!! NOTICE REMOVAL OF THIS INSTANTIATION STEP !!! | |
# import appmodels | |
def create_an_item(): | |
neomodel.db.set_connection(os.environ['NEO4J_BOLT_URL']) | |
appmodels.Item(name='Something Something Dark Side').save() | |
def create_app(): | |
""" | |
This is the original way presented to create a class. Please note | |
the inline comments throughout | |
""" | |
# In this example a Flask application is created explicity. | |
app = flask.Flask(__name__) | |
neomodel.config.DATABASE_URL = os.environ['NEO4J_BOLT_URL'] | |
# At this point, the neomodel.db object has been initialised as expected | |
@app.route('/', methods=['GET']) | |
def get_all_items(): | |
# !!! NOTICE ADDITION OF THIS INITIALISATION STEP !!! | |
import appmodels | |
return flask.jsonify({'items': [item.name for item in appmodels.Item.nodes]}) | |
return app | |
if __name__ == "__main__": | |
# !!!PRIOR TO RUNNING THE APP, CREATE AT LEAST ONE Item IN THE DATABASE!!! | |
create_an_item() | |
# Comment the above line and uncomment the following two to launch the app | |
# flask_app = create_app() | |
# At this point, the neomodel.db object is configured and valid | |
# flask_app.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment