From 276268047ec3d3d116bd305f14b4ca9784cdacf8 Mon Sep 17 00:00:00 2001 From: twomac Date: Mon, 5 Oct 2020 12:51:44 -0700 Subject: [PATCH 1/4] adds createUserEmotion view - some cool shit ;) --- Neo4j Tutorials.txt | 13 +++ mr_project/mr_app/__init__.py | 8 ++ mr_project/mr_app/urls.py | 2 + mr_project/mr_app/views.py | 142 +++++++++++++++++++++++- mr_project/mr_project/settings.py | 1 + neo4j install and config instruction.md | 63 +++++++++++ readme.md | 4 + requirements.txt | 4 +- 8 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 Neo4j Tutorials.txt create mode 100644 neo4j install and config instruction.md diff --git a/Neo4j Tutorials.txt b/Neo4j Tutorials.txt new file mode 100644 index 0000000..d265bd5 --- /dev/null +++ b/Neo4j Tutorials.txt @@ -0,0 +1,13 @@ +Getting Started: https://neo4j.com/developer/get-started/ + +Neo4j operations manual: https://neo4j.com/docs/operations-manual/3.5/docker/clustering/ + +Graph Data Science Tutorials: https://neo4j.com/docs/graph-data-science/current/introduction/ + +Neo4j package for Python from Pypi: https://pypi.org/project/neo4j/ + +neo4j package for Python from Neo4j: https://neo4j.com/developer/python/ + +Cypher Manual: https://neo4j.com/docs/cypher-manual/current/introduction/ + +Django Tutorial Blog: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Introduction \ No newline at end of file diff --git a/mr_project/mr_app/__init__.py b/mr_project/mr_app/__init__.py index e69de29..340e730 100644 --- a/mr_project/mr_app/__init__.py +++ b/mr_project/mr_app/__init__.py @@ -0,0 +1,8 @@ +from neo4j import GraphDatabase + +uri = 'bolt://localhost:7687' + +DRIVER = GraphDatabase.driver(uri, auth=('neo4j', 'password')) + +USERS = ['Rob', 'Seon', 'Taylor', 'Udam'] +EMOTIONS = ['ecstatic', 'happy', 'sad', 'furious'] \ No newline at end of file diff --git a/mr_project/mr_app/urls.py b/mr_project/mr_app/urls.py index 3ef24d9..f14badd 100644 --- a/mr_project/mr_app/urls.py +++ b/mr_project/mr_app/urls.py @@ -4,4 +4,6 @@ urlpatterns = [ path('', views.index, name='index'), + path('createUserEmotion', views.create_user_emotion, name='create_user_emotion'), + path('getUserEmotion//', views.index), ] \ No newline at end of file diff --git a/mr_project/mr_app/views.py b/mr_project/mr_app/views.py index 36a074d..b8a7f82 100644 --- a/mr_project/mr_app/views.py +++ b/mr_project/mr_app/views.py @@ -1,9 +1,145 @@ +import json + from django.shortcuts import render # Create your views here. +from time import time +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound +import neo4j +from django.views.decorators.csrf import csrf_exempt +from requests import codes +from . import DRIVER, EMOTIONS, USERS +from datetime import datetime + +#WRITE TRANSACTION FUNCTIONS +def create_user_tx(tx, name): + result = tx.run('CREATE (u:User{name:$name}) RETURN u.name AS username', name=name) + record = result.single() + result.consume() + return record['username'] + + +def create_emotion_tx(tx, name): + result = tx.run('CREATE (em:Emotion {name:$name}) RETURN em.name AS emotion_label', name=name) + record = result.single() + result.consume() + return record['emotion_label'] + + +def create_epoch_relationship_between_user_and_emotion(tx, emotion, user, epoch_timestamp): + result = tx.run(f'MATCH (em:Emotion {{name:"{emotion}"}}), (u:User {{name:"{user}"}}) CREATE (u)-[ts:Timestamp{{epoch:"{epoch_timestamp}"}}]->(em) RETURN ts.epoch as seconds') + record = result.single() + result.consume() + return record['seconds'] + + +#EFFECTIVE READ TRANSACTIONS TO CHECK IF NODES EXIST OR NOT +def check_for_user(driver_arg, user_name): + with driver_arg.session() as session: + result = session.run("MATCH (n:User{ name:$user_name }) RETURN n.name AS name", user_name=user_name) + values = result.values() + if not values: + return False + else: + return True + + +def check_for_emotion(driver_arg, emotion_name): + with driver_arg.session() as session: + result = session.run("MATCH (n:Emotion{ name:$emotion_name }) RETURN n.name AS name", emotion_name=emotion_name) + values = result.values() + if not values: + return False + else: + return True + + +#FUNCTIONS THAT ACTUALLY CONNECT WITH THE DATABASE TO PERFORM TRANSACTIONS +def spawn_emotion_node(driver_arg, emotion): + with driver_arg.session() as session: + emotion_label = session.write_transaction(create_emotion_tx, emotion) + print(emotion_label) + + +def spawn_user_node(driver_arg, username): + with driver_arg.session() as session: + user_name = session.write_transaction(create_user_tx, username) + print(user_name) + + +def register_emotion(driver_arg, username, emotion): + epoch_timestamp = time() + with driver_arg.session() as session: + seconds = session.write_transaction(create_epoch_relationship_between_user_and_emotion, emotion, username, epoch_timestamp) + print(seconds) + + +def spawn_all_emotions(driver_arg, emotions_list): + n_emotions = len(emotions_list) + for i in range(n_emotions): + spawn_emotion_node(driver_arg, emotions_list[i]) + + +def add_users(driver_arg, users_list): + n_users = len(users_list) + for i in range(n_users): + spawn_user_node(driver_arg, users_list[i]) + + +@csrf_exempt +def create_user_emotion(request): + if request.method == 'POST': + body = json.loads(request.body) + user = '' + emotion = '' + + try: + user = body['user'] + emotion = body['emotion'] + except KeyError: + return HttpResponseBadRequest('Missing required key') + + if check_for_user(DRIVER, user) and check_for_emotion(DRIVER, emotion): + register_emotion(DRIVER, user, emotion) + elif check_for_user(DRIVER, user): + spawn_emotion_node(DRIVER, emotion) + register_emotion(DRIVER, user, emotion) + elif check_for_emotion(DRIVER, emotion): + spawn_user_node(DRIVER, user) + register_emotion(DRIVER, user, emotion) + else: + spawn_user_node(DRIVER, user) + spawn_emotion_node(DRIVER, emotion) + register_emotion(DRIVER, user, emotion) + return HttpResponse(status=codes.created) + + return HttpResponseNotFound() + + +@csrf_exempt +def index(request, user_id, emotion): + if request.method == 'POST': + body = json.loads(request.body) + asdf = body['asdf'] + return HttpResponse(f'you sent {asdf}') -from django.http import HttpResponse + if request.method == 'GET': + print(request.GET) + return HttpResponse(f'you sent user_id = {user_id} and emotion = {emotion}') + return HttpResponseNotFound() -def index(request): - return HttpResponse("Hello, world!") \ No newline at end of file + # return HttpResponse('''Hello, world! In the heavens above and on earth below, I alone will become the Honored One.
+ # Add 'Udam-ecstatic' to the end of your URL to be an ecstatic Udam.
+ # Add 'Udam-happy' to the end of your URL to be a happy Udam.
+ # Add 'Udam-sad' to the end of your URL to be a sad Udam.
+ # Add 'Udam-pissed' to the end of your URL to be a pissed Udam.
+ #
+ # Same for Rob and Taylor
+ #
+ # Add 'Python>C++' to be done.
+ # Add 'bloob-bloob-bloob' to be eh.
+ # Add 'Seon-the-Insayin' to the end of your URL to be the highest form of insanity in the universe.
+ # Add 'beating-Seon' to the end of your url to be a pissed Robert Coleman Dalton III.''') + # + # diff --git a/mr_project/mr_project/settings.py b/mr_project/mr_project/settings.py index 431b594..c096207 100644 --- a/mr_project/mr_project/settings.py +++ b/mr_project/mr_project/settings.py @@ -10,6 +10,7 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.1/ref/settings/ + """ from pathlib import Path diff --git a/neo4j install and config instruction.md b/neo4j install and config instruction.md new file mode 100644 index 0000000..c0a9c2e --- /dev/null +++ b/neo4j install and config instruction.md @@ -0,0 +1,63 @@ +# neo4j install + +## Initial Setup + +### Notes + +* OS is assumed to be Ubuntu 20.04 or a suitable alternative +* To make it easy to copy code, permissions have been left out. If you have questions about permissions, ask eons. + +### Prepare packages to be installed +`sudo apt update` + +###Install a Java disribution, we use OpenJDK 8. Enter y to confirm. +`sudo apt install open-11-jdk` +###Verify install. +`java -version` + +###Update package repository to include Neo4j. +``` +sudo wget -O - https://debian.neo4j.org/neotechnology.gpg.key | sudo apt-key add - +sudo echo 'deb https://debian.neo4j.org/repo stable/' | sudo tee -a /etc/apt/sources.list.d/neo4j.list +sudo apt-get update +``` + +###Install Neo4j. Enter y to confirm. +`sudo apt install neo4j` +###Verify install. +`neo4j --version` + +###Edit the neo4j configuration to accept database connection from anywhere and to disable web authentication. Also edit 0.0.0.0 to 127.0.0.1. +`sudo nano /etc/neo4j/neo4j.conf` +###Uncomment the following lines in the neo4j.conf +``` +dbms.connectors.default_listen_address=0.0.0.0 +dbms.security.auth_enabled=false +``` + +###Go to to open a neo4j session. +###If password needed, deafult user and password are both "neo4j". + + +##Starting Neo4j Service + +###To enable your local database so it is accessible from the neo4j browser session, you must use one of two commands + +`service neo4j start` + +###or + +`systemctl start neo4j` + +###Remember, before shutting down your computer, you should shut down your database by calling either of the above commands but replacing + +`start` + +###with + +`stop` + + + + + diff --git a/readme.md b/readme.md index 86cd90a..2505bf1 100644 --- a/readme.md +++ b/readme.md @@ -65,10 +65,14 @@ ln -s /usr/bin/python3.8 /usr/bin/python3 If python3-venv is not installed, install it through apt: `apt install python3-venv` +If python3-pip is not installed, install it through apt: +`apt install python3-pip` + ``` python3 -m venv . source ./bin/activate pip3 install -r requirements.txt +chmod +x ./mr_project/manage.py ``` ## Run Django diff --git a/requirements.txt b/requirements.txt index 2753814..1f7919e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ +wheel==0.34.2 django==3.1 -psycopg2==2.8.5 \ No newline at end of file +psycopg2==2.8.5 +neo4j==4.1.0 \ No newline at end of file From 873936bc2720346d0fc6c99480437c5f464e7902 Mon Sep 17 00:00:00 2001 From: twomac Date: Sat, 24 Oct 2020 16:34:37 -0700 Subject: [PATCH 2/4] adds getUserEmotion GET request --- mr_project/mr_app/urls.py | 2 +- mr_project/mr_app/views.py | 74 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/mr_project/mr_app/urls.py b/mr_project/mr_app/urls.py index f14badd..24d8eaa 100644 --- a/mr_project/mr_app/urls.py +++ b/mr_project/mr_app/urls.py @@ -5,5 +5,5 @@ urlpatterns = [ path('', views.index, name='index'), path('createUserEmotion', views.create_user_emotion, name='create_user_emotion'), - path('getUserEmotion//', views.index), + path('getUserEmotion', views.get_user_emotion, name='get_user_emotion'), ] \ No newline at end of file diff --git a/mr_project/mr_app/views.py b/mr_project/mr_app/views.py index b8a7f82..cda3a3a 100644 --- a/mr_project/mr_app/views.py +++ b/mr_project/mr_app/views.py @@ -54,6 +54,50 @@ def check_for_emotion(driver_arg, emotion_name): return True +def fetch_epochs_of_user_emotion_pair(driver_arg, user_name, emotion_name): + + with driver_arg.session() as session: + result = session.run('''MATCH (u)-[ts]->(em) WHERE u.name = $user_name AND em.name = $emotion_name RETURN + ts.epoch AS timestamps''', user_name=user_name, emotion_name=emotion_name) + + timestamp_list = [] + for record in result: + timestamp_list.append(record["timestamps"]) + + one_emotion_dict = { + "emotion": emotion_name, + "timestampList": timestamp_list + } + return one_emotion_dict + + +def fetch_all_emotions_of_one_user(driver_arg, user_name): + with driver_arg.session() as session: + result = session.run('''MATCH (u)-->(em) WHERE u.name = $user_name RETURN + em.name AS emotions''', user_name=user_name) + emotion_list = [] + for record in result: + if not record["emotions"] in emotion_list: + emotion_list.append(record["emotions"]) + return emotion_list + + +def get_all_user_emotions(driver_arg, user_name): + + emotions_of_user = fetch_all_emotions_of_one_user(driver_arg, user_name) + list_of_individual_emotion_dicts = [] + + for i in range(len(emotions_of_user)): + list_of_individual_emotion_dicts.append(fetch_epochs_of_user_emotion_pair(driver_arg, user_name, emotions_of_user[i])) + + dict_of_all_emotions_and_epochs = { + "user": user_name, + "emotionList": list_of_individual_emotion_dicts + } + + return dict_of_all_emotions_and_epochs + + #FUNCTIONS THAT ACTUALLY CONNECT WITH THE DATABASE TO PERFORM TRANSACTIONS def spawn_emotion_node(driver_arg, emotion): with driver_arg.session() as session: @@ -86,6 +130,36 @@ def add_users(driver_arg, users_list): spawn_user_node(driver_arg, users_list[i]) +@csrf_exempt +def get_user_emotion(request): + if request.method == 'GET': + query_arguments = request.GET + user = '' + emotion = '' + + try: + user = query_arguments['user'] + emotion = query_arguments['emotion'] + except KeyError: + return HttpResponseBadRequest('Missing required key') + + if check_for_user(DRIVER, user) and check_for_emotion(DRIVER, emotion): + epoch_dict = fetch_epochs_of_user_emotion_pair(DRIVER, user, emotion) + epoch_list = epoch_dict["timestampList"] + epoch_string = '' + for i in range(len(epoch_list)): + epoch_string = epoch_string + epoch_list[i] + '
' + return HttpResponse('''Good job! The user and emotion both exist, here are all their epochs!
+ username: {}
+ emotion: {}
+ epochs:
{} + '''.format(user, emotion, epoch_string)) + + return HttpResponseBadRequest('Slow down dawg! The user and/or emotion do not exist, ya need a spelling lesson?') + + return HttpResponseNotFound() + + @csrf_exempt def create_user_emotion(request): if request.method == 'POST': From 619fe2c3e1d0ec837327098097f271bc8117de08 Mon Sep 17 00:00:00 2001 From: twomac Date: Mon, 26 Oct 2020 16:56:35 -0700 Subject: [PATCH 3/4] adds getAllUserEmotions view - properly returns JSON objects --- mr_project/mr_app/urls.py | 1 + mr_project/mr_app/views.py | 34 +++++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/mr_project/mr_app/urls.py b/mr_project/mr_app/urls.py index 24d8eaa..5fb8dbe 100644 --- a/mr_project/mr_app/urls.py +++ b/mr_project/mr_app/urls.py @@ -6,4 +6,5 @@ path('', views.index, name='index'), path('createUserEmotion', views.create_user_emotion, name='create_user_emotion'), path('getUserEmotion', views.get_user_emotion, name='get_user_emotion'), + path('getAllUserEmotions', views.get_all_user_emotions, name='get_user_emotion'), ] \ No newline at end of file diff --git a/mr_project/mr_app/views.py b/mr_project/mr_app/views.py index cda3a3a..510ef44 100644 --- a/mr_project/mr_app/views.py +++ b/mr_project/mr_app/views.py @@ -4,7 +4,7 @@ # Create your views here. from time import time -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound, JsonResponse import neo4j from django.views.decorators.csrf import csrf_exempt from requests import codes @@ -82,7 +82,7 @@ def fetch_all_emotions_of_one_user(driver_arg, user_name): return emotion_list -def get_all_user_emotions(driver_arg, user_name): +def fetch_all_emotions_and_epochs_of_user(driver_arg, user_name): emotions_of_user = fetch_all_emotions_of_one_user(driver_arg, user_name) list_of_individual_emotion_dicts = [] @@ -145,21 +145,33 @@ def get_user_emotion(request): if check_for_user(DRIVER, user) and check_for_emotion(DRIVER, emotion): epoch_dict = fetch_epochs_of_user_emotion_pair(DRIVER, user, emotion) - epoch_list = epoch_dict["timestampList"] - epoch_string = '' - for i in range(len(epoch_list)): - epoch_string = epoch_string + epoch_list[i] + '
' - return HttpResponse('''Good job! The user and emotion both exist, here are all their epochs!
- username: {}
- emotion: {}
- epochs:
{} - '''.format(user, emotion, epoch_string)) + return JsonResponse(epoch_dict) return HttpResponseBadRequest('Slow down dawg! The user and/or emotion do not exist, ya need a spelling lesson?') return HttpResponseNotFound() +@csrf_exempt +def get_all_user_emotions(request): + if request.method == 'GET': + query_arguments = request.GET + user = '' + + try: + user = query_arguments['user'] + except KeyError: + return HttpResponseBadRequest('Missing required key') + + if check_for_user(DRIVER, user): + all_epochs_dict = fetch_all_emotions_and_epochs_of_user(DRIVER, user) + + return JsonResponse(all_epochs_dict) + return HttpResponseBadRequest('Slow down dawg! The user does not exist, ya need a spelling lesson?') + + return HttpResponseNotFound() + + @csrf_exempt def create_user_emotion(request): if request.method == 'POST': From 65df64732f29db1924637c54f1f39ef812494196 Mon Sep 17 00:00:00 2001 From: twomac Date: Sun, 8 Nov 2020 14:57:20 -0800 Subject: [PATCH 4/4] clean up lots of logic --- Neo4j Tutorials.txt | 13 -- mr.env | 3 + mr_project/mr_app/__init__.py | 11 +- mr_project/mr_app/neo4j_transactions.py | 71 ++++++++ mr_project/mr_app/views.py | 213 +++++------------------- mr_project/mr_project/settings.py | 1 - neo4j install and config instruction.md | 9 +- 7 files changed, 124 insertions(+), 197 deletions(-) delete mode 100644 Neo4j Tutorials.txt create mode 100644 mr_project/mr_app/neo4j_transactions.py diff --git a/Neo4j Tutorials.txt b/Neo4j Tutorials.txt deleted file mode 100644 index d265bd5..0000000 --- a/Neo4j Tutorials.txt +++ /dev/null @@ -1,13 +0,0 @@ -Getting Started: https://neo4j.com/developer/get-started/ - -Neo4j operations manual: https://neo4j.com/docs/operations-manual/3.5/docker/clustering/ - -Graph Data Science Tutorials: https://neo4j.com/docs/graph-data-science/current/introduction/ - -Neo4j package for Python from Pypi: https://pypi.org/project/neo4j/ - -neo4j package for Python from Neo4j: https://neo4j.com/developer/python/ - -Cypher Manual: https://neo4j.com/docs/cypher-manual/current/introduction/ - -Django Tutorial Blog: https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Introduction \ No newline at end of file diff --git a/mr.env b/mr.env index 9d0c63e..27eedae 100644 --- a/mr.env +++ b/mr.env @@ -5,3 +5,6 @@ export MR_PG_HOST='127.0.0.1' export MR_PG_PORT='5432' export MR_SECRET_KEY='%mh)t%pn@+dq-@&-7amfjc_k23syz4+4*a5%-c77#jiz-f^=uv' +export NEO4J_URI='bolt://localhost:7687' +export NEO4J_USER='neo4j' +export NEO4J_PASSWORD='password' \ No newline at end of file diff --git a/mr_project/mr_app/__init__.py b/mr_project/mr_app/__init__.py index 340e730..01e48ad 100644 --- a/mr_project/mr_app/__init__.py +++ b/mr_project/mr_app/__init__.py @@ -1,8 +1,9 @@ -from neo4j import GraphDatabase +import os -uri = 'bolt://localhost:7687' +from neo4j import GraphDatabase -DRIVER = GraphDatabase.driver(uri, auth=('neo4j', 'password')) +uri = os.environ['NEO4J_URI'] +user = os.environ['NEO4J_USER'] +password = os.environ['NEO4J_PASSWORD'] -USERS = ['Rob', 'Seon', 'Taylor', 'Udam'] -EMOTIONS = ['ecstatic', 'happy', 'sad', 'furious'] \ No newline at end of file +DRIVER = GraphDatabase.driver(uri, auth=(user, password)) \ No newline at end of file diff --git a/mr_project/mr_app/neo4j_transactions.py b/mr_project/mr_app/neo4j_transactions.py new file mode 100644 index 0000000..fa0a5e6 --- /dev/null +++ b/mr_project/mr_app/neo4j_transactions.py @@ -0,0 +1,71 @@ +from time import time + + +def create_node_transaction(tx, label, property, property_value): + tx.run(f'CREATE (node:{label} {{{property}: "{property_value}"}})') + + +def create_epoch_relationship_between_user_and_emotion(tx, emotion, user, epoch_timestamp): + tx.run(f'MATCH (em:Emotion {{name:"{emotion}"}}), (u:User {{name:"{user}"}}) CREATE (u)-[ts:Timestamp{{epoch:"{epoch_timestamp}"}}]->(em) RETURN ts.epoch as seconds') + + +#EFFECTIVE READ TRANSACTIONS TO CHECK IF NODES EXIST OR NOT +def get_node(driver, label, property, property_value): + with driver.session() as session: + return session.run(f'MATCH (node:{label}{{ {property}: "{property_value}" }}) RETURN node.{property} as {property}').values() + + +def check_for_user(driver, username): + return True if get_node(driver, 'User', 'name', username) else False + + +def check_for_emotion(driver, emotion_name): + return True if get_node(driver, 'Emotion', 'name', emotion_name) else False + + +def fetch_epochs_of_user_emotion_pair(driver_arg, user_name, emotion_name): + with driver_arg.session() as session: + result = session.run('''MATCH (u)-[ts]->(em) WHERE u.name = $user_name AND em.name = $emotion_name RETURN + ts.epoch AS timestamps''', user_name=user_name, emotion_name=emotion_name) + return { + 'emotion': emotion_name, + 'timestampList': [record['timestamps'] for record in result] + } + + +def fetch_all_emotions_of_one_user(driver_arg, user_name): + with driver_arg.session() as session: + result = session.run('''MATCH (u)-->(em) WHERE u.name = $user_name RETURN + em.name AS emotions''', user_name=user_name) + return set([record['emotions'] for record in result]) + + +def fetch_all_emotions_and_epochs_of_user(driver_arg, user_name): + emotions_of_user = fetch_all_emotions_of_one_user(driver_arg, user_name) + + return { + 'user': user_name, + 'emotionList': [fetch_epochs_of_user_emotion_pair(driver_arg, user_name, emotion) for emotion in emotions_of_user] + } + + +#FUNCTIONS THAT ACTUALLY CONNECT WITH THE DATABASE TO PERFORM TRANSACTIONS +def spawn_emotion_node(driver_arg, emotion): + with driver_arg.session() as session: + emotion_label = session.write_transaction(create_node_transaction, 'Emotion', 'name', emotion) + print(emotion_label) + + +def spawn_user_node(driver_arg, username): + with driver_arg.session() as session: + user_name = session.write_transaction(create_node_transaction, 'User', 'name', username) + print(user_name) + + +def register_emotion(driver_arg, username, emotion): + epoch_timestamp = time() + with driver_arg.session() as session: + seconds = session.write_transaction(create_epoch_relationship_between_user_and_emotion, emotion, username, epoch_timestamp) + print(seconds) + + diff --git a/mr_project/mr_app/views.py b/mr_project/mr_app/views.py index 510ef44..265d9b2 100644 --- a/mr_project/mr_app/views.py +++ b/mr_project/mr_app/views.py @@ -1,153 +1,41 @@ import json +from json import JSONDecodeError -from django.shortcuts import render - -# Create your views here. -from time import time from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound, JsonResponse -import neo4j from django.views.decorators.csrf import csrf_exempt from requests import codes -from . import DRIVER, EMOTIONS, USERS -from datetime import datetime - -#WRITE TRANSACTION FUNCTIONS -def create_user_tx(tx, name): - result = tx.run('CREATE (u:User{name:$name}) RETURN u.name AS username', name=name) - record = result.single() - result.consume() - return record['username'] - - -def create_emotion_tx(tx, name): - result = tx.run('CREATE (em:Emotion {name:$name}) RETURN em.name AS emotion_label', name=name) - record = result.single() - result.consume() - return record['emotion_label'] - - -def create_epoch_relationship_between_user_and_emotion(tx, emotion, user, epoch_timestamp): - result = tx.run(f'MATCH (em:Emotion {{name:"{emotion}"}}), (u:User {{name:"{user}"}}) CREATE (u)-[ts:Timestamp{{epoch:"{epoch_timestamp}"}}]->(em) RETURN ts.epoch as seconds') - record = result.single() - result.consume() - return record['seconds'] - - -#EFFECTIVE READ TRANSACTIONS TO CHECK IF NODES EXIST OR NOT -def check_for_user(driver_arg, user_name): - with driver_arg.session() as session: - result = session.run("MATCH (n:User{ name:$user_name }) RETURN n.name AS name", user_name=user_name) - values = result.values() - if not values: - return False - else: - return True - - -def check_for_emotion(driver_arg, emotion_name): - with driver_arg.session() as session: - result = session.run("MATCH (n:Emotion{ name:$emotion_name }) RETURN n.name AS name", emotion_name=emotion_name) - values = result.values() - if not values: - return False - else: - return True - - -def fetch_epochs_of_user_emotion_pair(driver_arg, user_name, emotion_name): - - with driver_arg.session() as session: - result = session.run('''MATCH (u)-[ts]->(em) WHERE u.name = $user_name AND em.name = $emotion_name RETURN - ts.epoch AS timestamps''', user_name=user_name, emotion_name=emotion_name) - - timestamp_list = [] - for record in result: - timestamp_list.append(record["timestamps"]) - - one_emotion_dict = { - "emotion": emotion_name, - "timestampList": timestamp_list - } - return one_emotion_dict - - -def fetch_all_emotions_of_one_user(driver_arg, user_name): - with driver_arg.session() as session: - result = session.run('''MATCH (u)-->(em) WHERE u.name = $user_name RETURN - em.name AS emotions''', user_name=user_name) - emotion_list = [] - for record in result: - if not record["emotions"] in emotion_list: - emotion_list.append(record["emotions"]) - return emotion_list - - -def fetch_all_emotions_and_epochs_of_user(driver_arg, user_name): - - emotions_of_user = fetch_all_emotions_of_one_user(driver_arg, user_name) - list_of_individual_emotion_dicts = [] - - for i in range(len(emotions_of_user)): - list_of_individual_emotion_dicts.append(fetch_epochs_of_user_emotion_pair(driver_arg, user_name, emotions_of_user[i])) - - dict_of_all_emotions_and_epochs = { - "user": user_name, - "emotionList": list_of_individual_emotion_dicts - } - - return dict_of_all_emotions_and_epochs - - -#FUNCTIONS THAT ACTUALLY CONNECT WITH THE DATABASE TO PERFORM TRANSACTIONS -def spawn_emotion_node(driver_arg, emotion): - with driver_arg.session() as session: - emotion_label = session.write_transaction(create_emotion_tx, emotion) - print(emotion_label) - -def spawn_user_node(driver_arg, username): - with driver_arg.session() as session: - user_name = session.write_transaction(create_user_tx, username) - print(user_name) - - -def register_emotion(driver_arg, username, emotion): - epoch_timestamp = time() - with driver_arg.session() as session: - seconds = session.write_transaction(create_epoch_relationship_between_user_and_emotion, emotion, username, epoch_timestamp) - print(seconds) - - -def spawn_all_emotions(driver_arg, emotions_list): - n_emotions = len(emotions_list) - for i in range(n_emotions): - spawn_emotion_node(driver_arg, emotions_list[i]) - - -def add_users(driver_arg, users_list): - n_users = len(users_list) - for i in range(n_users): - spawn_user_node(driver_arg, users_list[i]) +from . import DRIVER +from .neo4j_transactions import * @csrf_exempt def get_user_emotion(request): if request.method == 'GET': - query_arguments = request.GET user = '' emotion = '' try: - user = query_arguments['user'] - emotion = query_arguments['emotion'] + user = request.GET['user'] except KeyError: - return HttpResponseBadRequest('Missing required key') + return HttpResponseBadRequest('Missing required "user" key') + + try: + emotion = request.GET['emotion'] + except KeyError: + return HttpResponseBadRequest('Missing required "emotion" key') if check_for_user(DRIVER, user) and check_for_emotion(DRIVER, emotion): - epoch_dict = fetch_epochs_of_user_emotion_pair(DRIVER, user, emotion) + return JsonResponse(fetch_epochs_of_user_emotion_pair(DRIVER, user, emotion)) + + # change these to HttpResponseNotFound instead of HttpResponseBadRequest + if check_for_user(DRIVER, user): + return HttpResponseNotFound('Slow down dawg! The emotion does not exist, ya need a spelling lesson?') + + if check_for_emotion(DRIVER, emotion): + return HttpResponseNotFound('Slow down dawg! The user does not exist, ya need a spelling lesson?') - return JsonResponse(epoch_dict) - return HttpResponseBadRequest('Slow down dawg! The user and/or emotion do not exist, ya need a spelling lesson?') + return HttpResponseNotFound('Slow down dawg! The user and emotion do not exist, ya need a spelling lesson?') return HttpResponseNotFound() @@ -155,19 +43,15 @@ def get_user_emotion(request): @csrf_exempt def get_all_user_emotions(request): if request.method == 'GET': - query_arguments = request.GET user = '' - try: - user = query_arguments['user'] + user = request.GET['user'] except KeyError: - return HttpResponseBadRequest('Missing required key') + return HttpResponseBadRequest('Missing required "user" key') if check_for_user(DRIVER, user): - all_epochs_dict = fetch_all_emotions_and_epochs_of_user(DRIVER, user) - - return JsonResponse(all_epochs_dict) - return HttpResponseBadRequest('Slow down dawg! The user does not exist, ya need a spelling lesson?') + return JsonResponse(fetch_all_emotions_and_epochs_of_user(DRIVER, user)) + return HttpResponseNotFound('Slow down dawg! The user does not exist, ya need a spelling lesson?') return HttpResponseNotFound() @@ -175,28 +59,33 @@ def get_all_user_emotions(request): @csrf_exempt def create_user_emotion(request): if request.method == 'POST': - body = json.loads(request.body) + body = {} user = '' emotion = '' + try: + body = json.loads(request.body) + except JSONDecodeError: + return HttpResponseBadRequest('Payload received was not a JSON') + try: user = body['user'] + except KeyError: + return HttpResponseBadRequest('Missing required "user" key') + + try: emotion = body['emotion'] except KeyError: - return HttpResponseBadRequest('Missing required key') + return HttpResponseBadRequest('Missing required "emotion" key') - if check_for_user(DRIVER, user) and check_for_emotion(DRIVER, emotion): - register_emotion(DRIVER, user, emotion) - elif check_for_user(DRIVER, user): - spawn_emotion_node(DRIVER, emotion) - register_emotion(DRIVER, user, emotion) - elif check_for_emotion(DRIVER, emotion): - spawn_user_node(DRIVER, user) - register_emotion(DRIVER, user, emotion) - else: + if not check_for_user(DRIVER, user): spawn_user_node(DRIVER, user) + + if not check_for_emotion(DRIVER, emotion): spawn_emotion_node(DRIVER, emotion) - register_emotion(DRIVER, user, emotion) + + register_emotion(DRIVER, user, emotion) + return HttpResponse(status=codes.created) return HttpResponseNotFound() @@ -205,27 +94,9 @@ def create_user_emotion(request): @csrf_exempt def index(request, user_id, emotion): if request.method == 'POST': - body = json.loads(request.body) - asdf = body['asdf'] - return HttpResponse(f'you sent {asdf}') + return HttpResponse('From the heavens above to the Earth below, I alone will become the honored one.') if request.method == 'GET': - print(request.GET) - return HttpResponse(f'you sent user_id = {user_id} and emotion = {emotion}') + return HttpResponse('From the heavens above to the Earth below, I alone will become the honored one.') return HttpResponseNotFound() - - # return HttpResponse('''Hello, world! In the heavens above and on earth below, I alone will become the Honored One.
- # Add 'Udam-ecstatic' to the end of your URL to be an ecstatic Udam.
- # Add 'Udam-happy' to the end of your URL to be a happy Udam.
- # Add 'Udam-sad' to the end of your URL to be a sad Udam.
- # Add 'Udam-pissed' to the end of your URL to be a pissed Udam.
- #
- # Same for Rob and Taylor
- #
- # Add 'Python>C++' to be done.
- # Add 'bloob-bloob-bloob' to be eh.
- # Add 'Seon-the-Insayin' to the end of your URL to be the highest form of insanity in the universe.
- # Add 'beating-Seon' to the end of your url to be a pissed Robert Coleman Dalton III.''') - # - # diff --git a/mr_project/mr_project/settings.py b/mr_project/mr_project/settings.py index c096207..431b594 100644 --- a/mr_project/mr_project/settings.py +++ b/mr_project/mr_project/settings.py @@ -10,7 +10,6 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/3.1/ref/settings/ - """ from pathlib import Path diff --git a/neo4j install and config instruction.md b/neo4j install and config instruction.md index c0a9c2e..ac400f1 100644 --- a/neo4j install and config instruction.md +++ b/neo4j install and config instruction.md @@ -10,7 +10,7 @@ ### Prepare packages to be installed `sudo apt update` -###Install a Java disribution, we use OpenJDK 8. Enter y to confirm. +###Install a Java disribution, we use OpenJDK 11. Enter y to confirm. `sudo apt install open-11-jdk` ###Verify install. `java -version` @@ -55,9 +55,4 @@ dbms.security.auth_enabled=false ###with -`stop` - - - - - +`stop` \ No newline at end of file