From 7f6f246073f237c241696533a330906093c91d10 Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Sat, 15 Jan 2022 20:30:16 +0530 Subject: [PATCH 01/16] Added get and post methods --- app.py | 70 ++++++++++++++++++++++++++++++++++++++++++-- templates/index.html | 28 ++++++++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 templates/index.html diff --git a/app.py b/app.py index 5fbfd70..e6a70ab 100644 --- a/app.py +++ b/app.py @@ -1,10 +1,74 @@ -from flask import Flask +from flask import Flask, jsonify, request, render_template # creating an app from Flask class app = Flask(__name__) -# letting the application know what requests it will understand + +stores = [ + { + "name": "My store", + "items": [ + { + "name": "My item", + "price": 12.99 + } + ] + } +] + @app.route('/') def home(): - return "Hello World!" + return render_template('index.html') + +# POST /store data: {name:} +@app.route('/store', methods=['POST']) +def create_store(): + request_data = request.get_json() + new_store = { + 'name': request_data['name'], + 'items': [], + } + stores.append(new_store) + return jsonify(new_store) + +# GET /store/ +@app.route('/store/') # http://127.0.0.1:5000/store/some_name +def get_store(name): # here 'some_name' has to be the 'name' + # iterate over stores + # return the name when matches + # if none matches, return error message + for store in stores: + if store['name'] == name: + return jsonify(store) + else: + return jsonify({"messege":"Store not found!"}) + +# GET /store +@app.route('/store') +def get_stores(): + return jsonify({'stores': stores}) + +# POST /store//item {name:, price:} +@app.route('/store//item', methods=['POST']) +def create_item_in_store(name): + request_data = request.get_json() + for store in stores: + if store["name"] == name: + new_item = { + "name": request_data["name"], + "price": request_data["price"] + } + store['items'].append(new_item) + return jsonify(new_item) + + return jsonify({"messege": "Store not found"}) + +# GET /store//item +@app.route('/store//item') +def get_item_from_store(name): + for store in stores: + if store['name'] == name: + return jsonify({"items":store['items']}) + + return jsonify({"messege": "Store not found"}) # run the app in specified folder app.run(port=5000) \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..e3e7cf3 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,28 @@ + + + + + + + + + +
+ Hello, world! +
+ + \ No newline at end of file From ee3d1210caf3cd0d5c4afd91ab08bd08fc8c361f Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Sat, 15 Jan 2022 20:31:37 +0530 Subject: [PATCH 02/16] Added README --- README.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..901d1b5 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +# REST API application made with flask. +Contains <> branches + +Final and stable application is in the master branch \ No newline at end of file From 0e3861813c33e0e4ab49db1c47cfd617703a186c Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Sun, 16 Jan 2022 15:23:33 +0530 Subject: [PATCH 03/16] Initial Commit --- app.py | 77 ++++++---------------------------------------------------- 1 file changed, 8 insertions(+), 69 deletions(-) diff --git a/app.py b/app.py index e6a70ab..bd6f87e 100644 --- a/app.py +++ b/app.py @@ -1,74 +1,13 @@ -from flask import Flask, jsonify, request, render_template -# creating an app from Flask class -app = Flask(__name__) - -stores = [ - { - "name": "My store", - "items": [ - { - "name": "My item", - "price": 12.99 - } - ] - } -] - -@app.route('/') -def home(): - return render_template('index.html') - -# POST /store data: {name:} -@app.route('/store', methods=['POST']) -def create_store(): - request_data = request.get_json() - new_store = { - 'name': request_data['name'], - 'items': [], - } - stores.append(new_store) - return jsonify(new_store) +from flask import Flask +from flask_restful import Resource, Api -# GET /store/ -@app.route('/store/') # http://127.0.0.1:5000/store/some_name -def get_store(name): # here 'some_name' has to be the 'name' - # iterate over stores - # return the name when matches - # if none matches, return error message - for store in stores: - if store['name'] == name: - return jsonify(store) - else: - return jsonify({"messege":"Store not found!"}) - -# GET /store -@app.route('/store') -def get_stores(): - return jsonify({'stores': stores}) - -# POST /store//item {name:, price:} -@app.route('/store//item', methods=['POST']) -def create_item_in_store(name): - request_data = request.get_json() - for store in stores: - if store["name"] == name: - new_item = { - "name": request_data["name"], - "price": request_data["price"] - } - store['items'].append(new_item) - return jsonify(new_item) +app = Flask(__name__) +api = Api(app) - return jsonify({"messege": "Store not found"}) +class Student(Resource): + def get(self, name): + return {"student": name} -# GET /store//item -@app.route('/store//item') -def get_item_from_store(name): - for store in stores: - if store['name'] == name: - return jsonify({"items":store['items']}) - - return jsonify({"messege": "Store not found"}) +api.add_resource(Student, '/student/') # http://127.0.0.1:5000/student/Bob -# run the app in specified folder app.run(port=5000) \ No newline at end of file From 335d0a82771df22eb3430e9feac1607265d20056 Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Tue, 18 Jan 2022 11:51:23 +0530 Subject: [PATCH 04/16] added requirements.txt --- app.py | 31 ++++++++++++++++++++++++++----- requiements.txt | 3 +++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 requiements.txt diff --git a/app.py b/app.py index bd6f87e..44099cf 100644 --- a/app.py +++ b/app.py @@ -1,13 +1,34 @@ -from flask import Flask +from flask import Flask, request from flask_restful import Resource, Api app = Flask(__name__) api = Api(app) -class Student(Resource): +items = [] + +class Item(Resource): def get(self, name): - return {"student": name} + item = next(filter(lambda x: x["name"] == name, items), None) + return {"item": item}, 200 if item else 404 + + def post(self, name): + # if there already exists an item with "name", show a messege, and donot add the item + if next(filter(lambda x: x["name"] == name, items), None): + return {"messege": f"item {name} already exists"} ,400 + + data = request.get_json() # get_json(force=True) means, we don't need a content type header + item = { # flask will look into the content, and format the data. + "name": name, + "price": data["price"] + } + items.append(item) + return item, 201 # 201 is for CREATED status + +class ItemList(Resource): + def get(self): + return {"items": items} -api.add_resource(Student, '/student/') # http://127.0.0.1:5000/student/Bob +api.add_resource(Item, '/item/') +api.add_resource(ItemList, '/items') -app.run(port=5000) \ No newline at end of file +app.run(port=5000, debug=True) \ No newline at end of file diff --git a/requiements.txt b/requiements.txt new file mode 100644 index 0000000..0213c81 --- /dev/null +++ b/requiements.txt @@ -0,0 +1,3 @@ +Flask +Flask-RESTful +Flask-JWT \ No newline at end of file From c85794b40e40cb228e0b1056f98ff5ba19158e3d Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Tue, 18 Jan 2022 13:55:34 +0530 Subject: [PATCH 05/16] added authentication to app --- __pycache__/security.cpython-39.pyc | Bin 0 -> 858 bytes __pycache__/user.cpython-39.pyc | Bin 0 -> 442 bytes app.py | 15 +++++++++++++++ security.py | 20 ++++++++++++++++++++ user.py | 6 ++++++ 5 files changed, 41 insertions(+) create mode 100644 __pycache__/security.cpython-39.pyc create mode 100644 __pycache__/user.cpython-39.pyc create mode 100644 security.py create mode 100644 user.py diff --git a/__pycache__/security.cpython-39.pyc b/__pycache__/security.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3e357eac8809c82e2a937ab800d5c5e8fec0f52 GIT binary patch literal 858 zcmb7C&2AGh5cb%cWSee63S78xfWuxQetJSxg#=tfMS#O9D00^(-H^>LwpUfq=G49c zF965BlCMZey~2$P%q&V3^?<}k9?y(DpTC*0?De_~YOtjJZEQ+v{bm|wbhR5p0lK*c2$IXsCr`- z_b(Bf#o!|=-|MM$W}4Dvv<)N zYM8ScKJ$;km|YNdSRvL@=K6wrK78PzGA+E{s9*QhlgW`O<~ntDaOdA7cK+%9Qu5t5`tlWuSx-6AW6F*A{3?e=Na}%w9w*$Gt9kzysHxO^+$45TQ z6oI-`%zdBU&D4gcxq+w{?v!%1D5Of-f6uQmGq>;>5wO%C1|c+&QM{Avooe&pldfjN z%|M&7%^uz})Y7Cykk<4mKtHLeq{-iUrI`}V#fJxZp{j*Gr0-}cD}qRLe+NOI_j%a< E1M-5ZO#lD@ literal 0 HcmV?d00001 diff --git a/__pycache__/user.cpython-39.pyc b/__pycache__/user.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21686752f0d90a86a99c0817360d0922c3554b93 GIT binary patch literal 442 zcmY*T!AiqG5S`sEH53CP;@x8|{QwauhLnDGkV!F;HgUH_D!JJY@HhOWy$b$- zH&4E4Db!iso1NWxZzhl90U=Ii-}wjfmlTI#P>cY73c4dERvX}5XT*9!i7D{@FEpwV z;LkuMWr``&tXOX-Gi;#gh2EntUC~3sKIAUS8^E7~I@OV-PJ>lvz?unKl_n8)UmM3_?8|zV8C$WF&7IhOlItV=Uhw5~?3(AYSo-OBy?kmG_qUUWysf6< zHEh=*vbI`OOKW8nFDg=foVQpO9`1irOhT(nw>Au{oj1Iy<$i4K%POyTKQ4lPJNtl+ g Date: Tue, 18 Jan 2022 21:36:16 +0530 Subject: [PATCH 06/16] added delete and put methods --- __pycache__/security.cpython-39.pyc | Bin 858 -> 858 bytes app.py | 50 ++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/__pycache__/security.cpython-39.pyc b/__pycache__/security.cpython-39.pyc index a3e357eac8809c82e2a937ab800d5c5e8fec0f52..9d73ba2fbd937f52e589dcff5a187512be95d73e 100644 GIT binary patch delta 25 fcmcb`c8iTGk(ZZ?0SLaIn#lE!(Pc9yV;~a%T^$Dh delta 25 fcmcb`c8iTGk(ZZ?0SG?jPvrW?n6jCZF^~xWS-1wj diff --git a/app.py b/app.py index 2682f2a..ec608c0 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,5 @@ from flask import Flask, request -from flask_restful import Resource, Api +from flask_restful import Resource, Api, reqparse from flask_jwt import JWT, jwt_required from security import authenticate, identity @@ -21,17 +21,28 @@ items = [] class Item(Resource): + + parser = reqparse.RequestParser() + parser.add_argument("price", + type=float, + required=True, + help="This field cannot be blank" + ) + + # TO GET ITEM WITH NAME @jwt_required() def get(self, name): item = next(filter(lambda x: x["name"] == name, items), None) return {"item": item}, 200 if item else 404 + # TO POST AN ITEM def post(self, name): # if there already exists an item with "name", show a messege, and donot add the item if next(filter(lambda x: x["name"] == name, items), None): return {"messege": f"item {name} already exists"} ,400 - data = request.get_json() # get_json(force=True) means, we don't need a content type header + data = Item.parser.parse_args() + # data = request.get_json() # get_json(force=True) means, we don't need a content type header item = { # flask will look into the content, and format the data. "name": name, "price": data["price"] @@ -39,7 +50,42 @@ def post(self, name): items.append(item) return item, 201 # 201 is for CREATED status + # TO DELETE AN ITEM + def delete(self, name): + # use the items variable avalable globally + global items + # check if the item exists + item = next(filter(lambda x: x["name"] == name ,items), None) + # if doesn't exist, skip deleting + if item is None: + return {"messege": "Item don't exist"}, 400 + + # store all the elements of items variable into local item + # except the one that was selected to be deleted + items = list(filter(lambda x: x["name"] != name, items)) + return {"messege": "Item deleted"} + + # TO ADD OR UPDATE AN ITEM + def put(self, name): + data = Item.parser.parse_args() + # data = request.get_json() + item = next(filter(lambda x: x["name"] == name ,items), None) + # if item is not available, add it + if item is None: + item = { + "name": name, + "price": data["price"] + } + items.append(item) + # if item exists, update it + else: + item.update(data) + return item + + class ItemList(Resource): + + # TO GET ALL ITEMS def get(self): return {"items": items} From 697673844913cc0e1e271e34b47c7fde5290e282 Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Tue, 18 Jan 2022 21:44:09 +0530 Subject: [PATCH 07/16] modified README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 901d1b5..52cfe84 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # REST API application made with flask. Contains <> branches -Final and stable application is in the master branch \ No newline at end of file +Final and stable application is in the master branch + +Use a virtual environment with python 3.9 to run the application \ No newline at end of file From 1b65a9807c809086878f067248724af27bcb50de Mon Sep 17 00:00:00 2001 From: Subhadeep Mandal Date: Thu, 20 Jan 2022 12:21:11 +0530 Subject: [PATCH 08/16] minor changes --- .vscode/settings.json | 3 +++ __pycache__/security.cpython-39.pyc | Bin 858 -> 899 bytes __pycache__/user.cpython-39.pyc | Bin 442 -> 483 bytes app.py | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..56fb648 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "/usr/sbin/python" +} \ No newline at end of file diff --git a/__pycache__/security.cpython-39.pyc b/__pycache__/security.cpython-39.pyc index 9d73ba2fbd937f52e589dcff5a187512be95d73e..81cd5eb73d6371ebd8cf04a32c922e544ca71a26 100644 GIT binary patch delta 92 zcmcb`*38b8$ji&c00cXpPUQOQ;-_C!nx~(env$8QUtF4$k(iR2TA=TmQktAtl9`{U ukeHXE5S*V@Ql40psvl64pOuzs1It$ji&c00iGpP2~D3t?FVG6Ht_&m6}{q91~Dkl98Vm_a<5TXD8 diff --git a/__pycache__/user.cpython-39.pyc b/__pycache__/user.cpython-39.pyc index 21686752f0d90a86a99c0817360d0922c3554b93..c11d9fabeb5c1010e173558713b90a687f7aa257 100644 GIT binary patch delta 91 zcmdnR{Fs?5k(ZZ?0SIXAQk`s delta 50 zcmaFNyo;GDk(ZZ?0SE-rCUQNJR!p&q2`I|XN=+^)jtQtN$;i(Oat#hiEXa(RY{0k~ E0A+Fy&j0`b diff --git a/app.py b/app.py index ec608c0..b981a5c 100644 --- a/app.py +++ b/app.py @@ -43,7 +43,7 @@ def post(self, name): data = Item.parser.parse_args() # data = request.get_json() # get_json(force=True) means, we don't need a content type header - item = { # flask will look into the content, and format the data. + item = { # flask will look into the content, and format the data. "name": name, "price": data["price"] } From c8007f1e975a538dc87414f072a247bc21a70db4 Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Thu, 20 Jan 2022 20:46:20 +0530 Subject: [PATCH 09/16] added database and user registration --- .vscode/settings.json | 2 +- README.md | 10 +- __pycache__/security.cpython-39.pyc | Bin 899 -> 602 bytes __pycache__/user.cpython-39.pyc | Bin 483 -> 2034 bytes app.py | 190 ++++++++++++++-------------- create_tables.py | 10 ++ requiements.txt | 4 +- security.py | 32 ++--- templates/index.html | 54 ++++---- test/data.db | Bin 0 -> 12288 bytes test/test.py | 32 +++++ user.py | 93 +++++++++++++- 12 files changed, 272 insertions(+), 155 deletions(-) create mode 100644 create_tables.py create mode 100644 test/data.db create mode 100644 test/test.py diff --git a/.vscode/settings.json b/.vscode/settings.json index 56fb648..7e7f74b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "python.pythonPath": "/usr/sbin/python" + "python.pythonPath": "/usr/sbin/python3.9" } \ No newline at end of file diff --git a/README.md b/README.md index 52cfe84..1331531 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# REST API application made with flask. -Contains <> branches - -Final and stable application is in the master branch - +# REST API application made with flask. +Contains <> branches + +Final and stable application is in the master branch + Use a virtual environment with python 3.9 to run the application \ No newline at end of file diff --git a/__pycache__/security.cpython-39.pyc b/__pycache__/security.cpython-39.pyc index 81cd5eb73d6371ebd8cf04a32c922e544ca71a26..c398288b90f32042c7a50f6440c0306b27b74392 100644 GIT binary patch literal 602 zcmYjO%}(1u5Z+mv#6&@&y>USiH%k?M0R)vQt`Tb5i!avV*)$9Bk9OCJT$vMGc#CrE zEBV?Byh2aRI7-AwGdtg|=bQP)>gZ@9$X>7B)H4Y2kHJTi1iq5HFBDK9tVIDS0OxWo ziy#ds4={WZX^00nqVoX93lT?eR3T#Mr%o+(=Df}Fq9z>vblT=jyt9B3_HX3wjDi<` zpc60fAUkPKJ;l4AgGb6cxuDiW5A!&*T$CO!O^MlUn>EB+szO`l?xR{cx2Y_~K_Bg( zLVgMv{uOpi;Qu_aO_>xLjY?c|yHcoiom^v+D{rcDrb?VGs-@p3tCJgB-Ra!BAUDN|)YHz2s~V(EVJf51J3yd?@&Et; literal 899 zcmb7Cy^hmB5Z+xoi7)4b9MI6Eph*++bLHuT1lNWW0SZef+IaR7hxmuxwW1)W%Dn+E z0Oh>_&*Bz=bTu6f%oybqU4g_%JD!={`S$ZSD?6PwL;L#uhkPj*`$oyWxtKh|W!|C# z27Jj99&%2xSc=369nO>k4!F?RIx`-+(1g|{Q|=44`H1Coa=0%B5Q*4wVh|_tF!TIna6=qQK4hI9_H(+eFAZ0qb$i!J-p;6 zE~XFB{XhAdAo3S6=oZ1;u+}uW8nq65f+sz8=3sE6%|lEq`^-xm+!wJCrOosPbYUP`e(8s!R9Au;Z!kAS#wyxm+(Z z31Rc^{w-$u9v&kCh6G~V<8@^;I0%ncO27Z8irH{C(E7La5uVc|Y1kl0qq|g~Cs+ST j-M@EBJtdk;<((uM6ianV@77S4&wZ!;+jYC5E4=0(eq*_* diff --git a/__pycache__/user.cpython-39.pyc b/__pycache__/user.cpython-39.pyc index c11d9fabeb5c1010e173558713b90a687f7aa257..b04ff652ee70d85231b07deb2b65de705d8d2949 100644 GIT binary patch literal 2034 zcmcgt&2k$>5T2R+wfqws2-pEqdk6(GE{Q5`DT19!2}sH)DanQ^UAERcBYVwiSDu+I zM`C?)u24LJe9WWp3Uj46_As{L2$xpP6qg7IUTV98#x1ql5YujxciK7_nZw}7kuTV}Gw?X=lVPdrB9%yS?Rs-yumfFffe>UsITBGsz>WTKDCqSxu~CF87(MqA^F3F9~`G9AZgMWGwjnZs);Xv>AQVd;EQbo~!7`?>fDX)e*XT z+s}OysFOU?;!6{xWl=!P#!oA$N@)V|RHT&_gK#Kx3MdHUrFp3Yyg?_;m4(h zH}4mgmeFaZk0O1P=vOR_l3a>}Pa^RYa8Rx6H;81Oi=RB~_B*}3=wWy7@g>85xWBvK z=|`V+_jh-sfrr^P_%JWI<#qR(_b5Ta{Futw&(lqQd zPUNAo?|hyvH(-lgMPU>B9nc1TT8>7UmhZx#=}9bi#>Hy%CIep2FyoF(rR|Hb)Ta%$ z!j{|yg95V!iAb2`A@J#^7%H9yC?!^X d>&_gp2#5b+%!FUfN%}RWru~Y9bd{}a{SDw@(vAQC delta 242 zcmeyw|Cl*8k(ZZ?0SI-@NIwQ~kO4E0;{e3PLO{ZuA%!7@u?2{mnW7j{n1UHJ znUjIyD1Zsba{%IEk%t Dkf') -api.add_resource(ItemList, '/items') - +from flask import Flask, request +from flask_restful import Resource, Api, reqparse +from flask_jwt import JWT, jwt_required + +from security import authenticate, identity +from user import UserRegister + +app = Flask(__name__) + +app.secret_key = "komraishumtirkomchuri" + +api = Api(app) + +# JWT() creates a new endpoint: /auth +# we send an username and password to /auth +# JWT() gets the username and password, and sends it to authenticate function +# the authenticate function maps the username and checks the password +# if all goes well, the authenticate function returns user +# which is the identity or jwt(or token) +jwt = JWT(app, authenticate, identity) + +items = [] + +class Item(Resource): + + parser = reqparse.RequestParser() + parser.add_argument("price", + type=float, + required=True, + help="This field cannot be blank" + ) + + # TO GET ITEM WITH NAME + @jwt_required() + def get(self, name): + item = next(filter(lambda x: x["name"] == name, items), None) + return {"item": item}, 200 if item else 404 + + # TO POST AN ITEM + def post(self, name): + # if there already exists an item with "name", show a messege, and donot add the item + if next(filter(lambda x: x["name"] == name, items), None): + return {"messege": f"item {name} already exists"} ,400 + + data = Item.parser.parse_args() + # data = request.get_json() # get_json(force=True) means, we don't need a content type header + item = { # flask will look into the content, and format the data. + "name": name, + "price": data["price"] + } + items.append(item) + return item, 201 # 201 is for CREATED status + + # TO DELETE AN ITEM + def delete(self, name): + # use the items variable avalable globally + global items + # check if the item exists + item = next(filter(lambda x: x["name"] == name ,items), None) + # if doesn't exist, skip deleting + if item is None: + return {"messege": "Item don't exist"}, 400 + + # store all the elements of items variable into local item + # except the one that was selected to be deleted + items = list(filter(lambda x: x["name"] != name, items)) + return {"messege": "Item deleted"} + + # TO ADD OR UPDATE AN ITEM + def put(self, name): + data = Item.parser.parse_args() + # data = request.get_json() + item = next(filter(lambda x: x["name"] == name ,items), None) + # if item is not available, add it + if item is None: + item = { + "name": name, + "price": data["price"] + } + items.append(item) + # if item exists, update it + else: + item.update(data) + return item + + +class ItemList(Resource): + + # TO GET ALL ITEMS + def get(self): + return {"items": items} + +api.add_resource(Item, '/item/') +api.add_resource(ItemList, '/items') +api.add_resource(UserRegister, '/register') + app.run(port=5000, debug=True) \ No newline at end of file diff --git a/create_tables.py b/create_tables.py new file mode 100644 index 0000000..4889a69 --- /dev/null +++ b/create_tables.py @@ -0,0 +1,10 @@ +import sqlite3 + +connection = sqlite3.connect('./test/data.db') +cursor = connection.cursor() + +create_table = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username text, password text)" +cursor.execute(create_table) + +connection.commit() +connection.close() \ No newline at end of file diff --git a/requiements.txt b/requiements.txt index 0213c81..aaa2275 100644 --- a/requiements.txt +++ b/requiements.txt @@ -1,3 +1,3 @@ -Flask -Flask-RESTful +Flask +Flask-RESTful Flask-JWT \ No newline at end of file diff --git a/security.py b/security.py index 893ddf4..d8db52d 100644 --- a/security.py +++ b/security.py @@ -1,20 +1,12 @@ -from werkzeug.security import safe_str_cmp -from user import User - -users = [ - User(1, "bob", "1234") -] - -username_mapping = {u.username: u for u in users} # mapping the users using set comprehension - -userid_mapping = {u.id: u for u in users} - -def authenticate(username, password): - user = username_mapping.get(username, None) - # if user and user.password == password: - if user and safe_str_cmp(user.password, password): - return user - -def identity(payload): # payload is the contents of jwt - userid = payload["identity"] - return userid_mapping.get(userid, None) +from werkzeug.security import safe_str_cmp +from user import User + +def authenticate(username, password): + user = User.find_by_username(username) + # if user and user.password == password: + if user and safe_str_cmp(user.password, password): + return user + +def identity(payload): # payload is the contents of jwt + user_id = payload["identity"] + return User.find_by_id(user_id) diff --git a/templates/index.html b/templates/index.html index e3e7cf3..fb11bf2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,28 +1,28 @@ - - - - - - - - - -
- Hello, world! -
- + + + + + + + + + +
+ Hello, world! +
+ \ No newline at end of file diff --git a/test/data.db b/test/data.db new file mode 100644 index 0000000000000000000000000000000000000000..06724902c8b6e9fa88f3d2b97be4929e9ba0c30c GIT binary patch literal 12288 zcmeI&!AiqG5C-7cBq*XKf`nY>*wP|sy$NEJMT>2%F(N%lYPMQv8{19Mt8d`b`2@az z2k-6%daxJI%0FZ`nPp}V-)$h*SM5=uc$m*8X~9j}CL!pUnTR~IT(g!T%!fT&hRuHq zk9Kd*E2hfvkH~*B8v+6lfB*y_009U<00Izz00bcL=LCArT3D}(evuBwO3%h-l)lqy zwoudi)zm$WWt2!xqLa4dmD=hwov4QCtWCvw7>45Yu)K1i)m)dG^P{~y;_4{lRyUDn zGUi^~>O^s$FJzyio8+?9H4PovO&V;A?fqP+m!iQ>sn*Z=JS)?hoy}eUo%~P#!@Lj> zfB*y_009U<00Izz00bZa0SNpVfi2ggAb7~f+1`HhVAJtvCm7@dn^c5HVW20Y;xX0P q(9ZwD|044sAOHafKmY;|fB*y_009U<00I#BPXZgl4Mq76f%^@U|5-Bt literal 0 HcmV?d00001 diff --git a/test/test.py b/test/test.py new file mode 100644 index 0000000..eb1b92f --- /dev/null +++ b/test/test.py @@ -0,0 +1,32 @@ +import sqlite3 + +connection = sqlite3.connect('./test/data.db') + +cursor = connection.cursor() + +create_table = "CREATE TABLE IF NOT EXISTS users (id int PRIMARY KEY, username text, password text)" +cursor.execute(create_table) + +user1 = (1, "bob", "1234") + +insert_query = "INSERT INTO users VALUES (?, ?, ?)" + +cursor.execute(insert_query, user1) + +users = [ + (2, "rolf", "2345"), + (3, "smith", "3456"), + (4, "john", "4567"), + (5, "clint", "5678") +] + +cursor.executemany(insert_query, users) + +select_query = "SELECT username, password FROM users" +for row in cursor.execute(select_query): + print(row) + +# commiting the changes to database +connection.commit() +# closing the connection to database +connection.close() \ No newline at end of file diff --git a/user.py b/user.py index 354e8ff..dcca8df 100644 --- a/user.py +++ b/user.py @@ -1,6 +1,87 @@ -class User: - def __init__(self, _id, username, password): - self.id = _id - self.username = username - self.password = password - \ No newline at end of file +import sqlite3 +from flask_restful import Resource, reqparse + +class User: + + def __init__(self, _id, username, password): + self.id = _id + self.username = username + self.password = password + + @classmethod + def find_by_username(cls, username): + connection = sqlite3.connect('./test/data.db') + cursor = connection.cursor() + + query = "SELECT * FROM users WHERE username=?" + result = cursor.execute(query, (username,)) # parameters must be in the form of tuple. + + row = result.fetchone() + if row: + # user = cls(row[0], row[1], row[2]) + user = cls(*row) # is similar to passing all values of row + else: + user = None + + connection.close() + return user + + @classmethod + def find_by_id(cls, _id): + connection = sqlite3.connect('./test/data.db') + cursor = connection.cursor() + + query = "SELECT * FROM users WHERE id=?" + result = cursor.execute(query, (_id,)) # parameters must be in the form of tuple. + + row = result.fetchone() + if row: + # user = cls(row[0], row[1], row[2]) + user = cls(*row) # is similar to passing all values of row + else: + user = None + + connection.close() + return user + +# New user registraction class +class UserRegister(Resource): + # Creating a request parser + parser = reqparse.RequestParser() + # Adding username argument to parser + parser.add_argument( + "username", + type=str, + required=True, + help="This field cannot be empty" + ) + # Adding password argument to parser + parser.add_argument( + "password", + type=str, + required=True, + help="This field cannot be empty" + ) + + # calls to post a new user (new user registration) + def post(self): + data = UserRegister.parser.parse_args() + # First check if that user is present or not + if User.find_by_username(data["username"]): + # if exists, then don't add + return {"message": "An user with that username already exists."}, 400 + + # else...continue + # 1. Connect to database + connection = sqlite3.connect('./test/data.db') + # 2. Create database cursor + cursor = connection.cursor() + # 3. SQL query to inser new useer information + query = "INSERT INTO users VALUES (NULL, ?, ?)" + + cursor.execute(query, (data["username"], data["password"])) + # 4. Commit the changes and close the connection to database + connection.commit() + connection.close() + + return {"messege": "User added successfully."}, 201 \ No newline at end of file From 191924f1c07b055354770a6854fb733777388769 Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Thu, 20 Jan 2022 22:42:17 +0530 Subject: [PATCH 10/16] added database integration to get and post --- __pycache__/item.cpython-39.pyc | Bin 0 -> 2794 bytes __pycache__/user.cpython-39.pyc | Bin 2034 -> 2034 bytes app.py | 81 ++---------------------- create_tables.py | 5 +- item.py | 106 ++++++++++++++++++++++++++++++++ test/data.db | Bin 12288 -> 12288 bytes 6 files changed, 116 insertions(+), 76 deletions(-) create mode 100644 __pycache__/item.cpython-39.pyc create mode 100644 item.py diff --git a/__pycache__/item.cpython-39.pyc b/__pycache__/item.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e9bc6466ec2cc3f9c37118e862b6bcbd72d88cf GIT binary patch literal 2794 zcmb7G&2Jk;6rY)${jlSF^n=nAwOt8B*;2(og~Uf`gNh5OirdC1AYZJ_&bV>9-gRf! zYGQ3psYEYG91s_Zs;q-Ks!0+y_ zd*SpHA%9}y@Q*`d5x(pP5P}FAlQxztrhV3CeXDIzY+Et!+ikn=v>nstvD^3B9wlEB zVGHLm5stLCt#$?4uJEAknRZps76~eQusUf5Oxri&Fngd~B_9rDmP3!XEVFc|BB?#- z9E2*90oAqjM|lU8dP<52XCMAK&{%}eSS?AL3eslM8uJ~}wxzx92r6B{geCY-oD%76 zPpsUg?TW0H7D9bWR7CYLY1hP*s6ja`ro{}DGh!C3p3{6OmwjyyR4uC8o5Cs{Ng6_~QRxowE zU@gF3upSjw7wQ3TYPT=5EW9sAvpulH$1S_*FcAyAUnn7f)3I(Z5gi=ttZsIaurGJP zluX85&9S99j_ne49QJ#5v#y3oy)Q*CtY^d3wNOYos5itg3iDo?_+cXaR@%)Ug-X`% zsB~RMc~-x(nXjeEa-+2p4tjN5Z(*>ht@|=Rh9~hr5LTs}ayIgoa2SSOI=KrP=xOHU z%TUS5n2O2C$83jeS%Pix!WvrzFKCzUur0f=k-n;o(G?M z3TOdp1kiGu&t?|tIXG2agn76iR!4rTajS8C#lPs^Sib$OkCtct_un*@8$M$5#WjTo zP=F-aL$S-$9CqM|0!O>q!x-jV)^3z02|%HpXsEJOX;*H@XqW@tT{tO#BefmHDR{1{ zttigSGP*jM2FR*2u%x!Z=hdcml+1>4t}T^5GQ5=H1a3VI0(G;~AP`lLaXQ01EE%H? zb)NHoMyCwQuTcLA<`^di^8zaS-loo>mlgCki0a=h@HUR#meX}Mwg7J!DcC-`TUO4; zws65mdBMjHjN8HkPVBK;IE5uDz=eg{UADu3BR=*FSA1MCr6sDym!~GaEWwv;B*Guf z`eCeOC^mh$(aZ8|?`Pn^V6WZ;bJZIlM(3BBt;X_-ztmj0Jt6SBFK^vzwEXw3UGlF5 z2I;*&KsBfu@D%!*c1#{ox@yW!sP1P95moaj5McF|(Tmc4zn81C&Liv#EanxhYu z?r|PF%@iMN7)S?%X+B7^d;$70R6)j0vZ@74J$LMqz0-!hQN?hE+AqSK_e0D#EL1=U?!V(OGjUA!C`# zg)4Cyg>iNjDy5!!8+GPT#}{dGAup*`??Cr!nr5|#dLPtF$S+|H(LP{6)uDM8yFLIh zs+F4=gG9g~3(5@$+-@(T#F{;ZnA)L~Bvr_TZo#l# z00e>kKd5{SyzsU!@j7EpH5lecu!nij#A4u?uu|`0#|0E0qWB2KWf0m42LqW1?FgI?0OFdGwdg{$^dH2anBuIv#NA*mw-|;nAKj#+-{wYu68>8 zR19MY^;)O%a2Upz%{v{1BndI8;#%Y)Zo(MWFZ6 z55sT~z6|%@f54cCCv8h0;ar=m^cFbkk&$v8XCpy^=EOuh1Tbv;SC)`}J_D zd6>{LTyPV-vzx%%r!c5KL-9EZ)Iak0i!jiI&n)Cw3fsYyNwNqqJn|H7p)jxMY10Ak txh(GvV}$`zl2s`O;IUWIfqxXL~9b#T%4bSejZ~5|CI_oLW?*HrbY4oKbUf HDEnLhi>428 delta 53 zcmeyw|B0U~k(ZZ?0SL6KH*(pqG2WW&&h}LB7H?2$VQFe{NkC#zacWVK`ea*naYn7l Hq3m-3ru7hE diff --git a/app.py b/app.py index 0f51f54..1d2185f 100644 --- a/app.py +++ b/app.py @@ -1,9 +1,10 @@ -from flask import Flask, request -from flask_restful import Resource, Api, reqparse -from flask_jwt import JWT, jwt_required +from flask import Flask +from flask_restful import Api +from flask_jwt import JWT from security import authenticate, identity from user import UserRegister +from item import Item, ItemList app = Flask(__name__) @@ -19,79 +20,9 @@ # which is the identity or jwt(or token) jwt = JWT(app, authenticate, identity) -items = [] - -class Item(Resource): - - parser = reqparse.RequestParser() - parser.add_argument("price", - type=float, - required=True, - help="This field cannot be blank" - ) - - # TO GET ITEM WITH NAME - @jwt_required() - def get(self, name): - item = next(filter(lambda x: x["name"] == name, items), None) - return {"item": item}, 200 if item else 404 - - # TO POST AN ITEM - def post(self, name): - # if there already exists an item with "name", show a messege, and donot add the item - if next(filter(lambda x: x["name"] == name, items), None): - return {"messege": f"item {name} already exists"} ,400 - - data = Item.parser.parse_args() - # data = request.get_json() # get_json(force=True) means, we don't need a content type header - item = { # flask will look into the content, and format the data. - "name": name, - "price": data["price"] - } - items.append(item) - return item, 201 # 201 is for CREATED status - - # TO DELETE AN ITEM - def delete(self, name): - # use the items variable avalable globally - global items - # check if the item exists - item = next(filter(lambda x: x["name"] == name ,items), None) - # if doesn't exist, skip deleting - if item is None: - return {"messege": "Item don't exist"}, 400 - - # store all the elements of items variable into local item - # except the one that was selected to be deleted - items = list(filter(lambda x: x["name"] != name, items)) - return {"messege": "Item deleted"} - - # TO ADD OR UPDATE AN ITEM - def put(self, name): - data = Item.parser.parse_args() - # data = request.get_json() - item = next(filter(lambda x: x["name"] == name ,items), None) - # if item is not available, add it - if item is None: - item = { - "name": name, - "price": data["price"] - } - items.append(item) - # if item exists, update it - else: - item.update(data) - return item - - -class ItemList(Resource): - - # TO GET ALL ITEMS - def get(self): - return {"items": items} - api.add_resource(Item, '/item/') api.add_resource(ItemList, '/items') api.add_resource(UserRegister, '/register') -app.run(port=5000, debug=True) \ No newline at end of file +if __name__ == "__main__": + app.run(port=5000, debug=True) \ No newline at end of file diff --git a/create_tables.py b/create_tables.py index 4889a69..6afb122 100644 --- a/create_tables.py +++ b/create_tables.py @@ -3,7 +3,10 @@ connection = sqlite3.connect('./test/data.db') cursor = connection.cursor() -create_table = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username text, password text)" +create_table = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username text, password text)" +cursor.execute(create_table) + +create_table = "CREATE TABLE IF NOT EXISTS items (name text, price real)" cursor.execute(create_table) connection.commit() diff --git a/item.py b/item.py new file mode 100644 index 0000000..4dfffae --- /dev/null +++ b/item.py @@ -0,0 +1,106 @@ +import sqlite3 + +from flask import Flask, request +from flask_restful import Resource, reqparse +from flask_jwt import jwt_required + +class Item(Resource): + + parser = reqparse.RequestParser() + parser.add_argument("price", + type=float, + required=True, + help="This field cannot be blank" + ) + + # TO GET ITEM WITH NAME + @jwt_required() + def get(self, name): + item = self.find_item_by_name(name) + if item: + return item + + return {"message": "item not found."}, 404 + + # searches the database for items using name + @classmethod + def find_item_by_name(cls, name): + connection = sqlite3.connect('./test/data.db') + cursor = connection.cursor() + + query = "SELECT * FROM items WHERE name=?" + result = cursor.execute(query, (name,)) + + row = result.fetchone() + connection.close() + + if row: + return { + "item": { + "name": row[0], + "price": row[1] + } + } + + # TO POST AN ITEM + def post(self, name): + # if there already exists an item with "name", show a messege, and donot add the item + if self.find_item_by_name(name): + return {"messege": f"item {name} already exists"} ,400 + + data = Item.parser.parse_args() + # data = request.get_json() # get_json(force=True) means, we don't need a content type header + item = { # flask will look into the content, and format the data. + "name": name, + "price": data["price"] + } + + connection = sqlite3.connect("./test/data.db") + cursor = connection.cursor() + + query = "INSERT INTO items VALUES (?, ?)" + cursor.execute(query, (item["name"], item["price"])) + + connection.commit() + connection.close() + + return item, 201 # 201 is for CREATED status + + # TO DELETE AN ITEM + def delete(self, name): + # use the items variable avalable globally + global items + # check if the item exists + item = next(filter(lambda x: x["name"] == name ,items), None) + # if doesn't exist, skip deleting + if item is None: + return {"messege": "Item don't exist"}, 400 + + # store all the elements of items variable into local item + # except the one that was selected to be deleted + items = list(filter(lambda x: x["name"] != name, items)) + return {"messege": "Item deleted"} + + # TO ADD OR UPDATE AN ITEM + def put(self, name): + data = Item.parser.parse_args() + # data = request.get_json() + item = next(filter(lambda x: x["name"] == name ,items), None) + # if item is not available, add it + if item is None: + item = { + "name": name, + "price": data["price"] + } + items.append(item) + # if item exists, update it + else: + item.update(data) + return item + + +class ItemList(Resource): + + # TO GET ALL ITEMS + def get(self): + return {"items": items} \ No newline at end of file diff --git a/test/data.db b/test/data.db index 06724902c8b6e9fa88f3d2b97be4929e9ba0c30c..8edd7f0f3822d827500a1897594190c689202a4c 100644 GIT binary patch delta 172 zcmZojXh@i#&B!!S$Br$Afqx!<%w|D>H+Ol;!f;*5zUiAg!BnI);Y#bAQjImp#9 z#8n~0(aFbE0W74Tk(Zd8s!)Ng%ATjBeN)bQht86 MgZi(B?(0OV0o1H8<^TWy delta 226 zcmZojXh@i#&B!=W$Bxa8fqw$O-NwRme9-|+Y~tG5jFBaYNja&-g*llesqw|Bg{7%^ z$>>~W=O9Tk$D4hKBfi`T@22 zy84Aoe#o!P#ms+=f&U}_6aH(P1qDv Date: Fri, 21 Jan 2022 17:00:31 +0530 Subject: [PATCH 11/16] implemeted delete method --- .gitignore | 2 + __pycache__/item.cpython-39.pyc | Bin 2794 -> 3025 bytes item.py | 79 ++++++++++++++++++++------------ test/data.db | Bin 12288 -> 12288 bytes test/test.db | Bin 0 -> 12288 bytes test/test.py | 14 +++--- 6 files changed, 60 insertions(+), 35 deletions(-) create mode 100644 .gitignore create mode 100644 test/test.db diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f714eb5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +./test/test.py +./test/test.db \ No newline at end of file diff --git a/__pycache__/item.cpython-39.pyc b/__pycache__/item.cpython-39.pyc index 7e9bc6466ec2cc3f9c37118e862b6bcbd72d88cf..97519cb561e2b0bfa7498383f9ca3c5baa2c3338 100644 GIT binary patch delta 1616 zcmah}OK%)S5bo-E?Ck7%?2YZj2FDp7!3+c^kwb!c7{$(7AcBKzOA(fWGj`89EA7MS znH9-ut(9;jByLd)$r2pA+{_Q)#t#U$aMP?$JhOM z^uaMN92jsJe&6ps4sR6ic@II{`)z7oSi-)`c3~|aIU*+Knc{mYUThs!PB_9uXYy)NF+HNWEjMUKqxS)VkG* z?Bo#w@=}fbODpTTh)rFOLuM>08uT zsJuBl-S#?c-|QGY0CtTvMgSwlSV82fV6!hU=CiD02&cj^`n>wqeA^#HEA7&yh961U zlzww_vn3-j{pdbFZ zhabt4q*NqF{jP{=Q4)#vkQPO=F_rky?P{Dzs&A0fwR;hJ>{U3F*iogfq;qPN zN**{ehn<`vcmqK}?r30#+uKn?q;_i?3mnOSRy6^qX{0S0+pXkF^`rAT45|ChY?myg z#ZZX#P;RyAQ6ovMO05|tX<@S##&JDLZZ<`hA)l-eXXR@IZxNg(xIoZnx*pMK+DURW zrrY6Q^fqw%|FUx&++l2P!35WFMw}t_b^h~FvVM3g)==1DJD~RXM7IZ*+4YGXs{_ax zOFs}6JrKhBfzyS#brN~=Z~oXFApQhTIWxS1oLN})-+YEO`k9j+o+K%;as~kz@t>!p zi)-gep-%}ryHT{`c}l!YbNz(qTPC}Z*35sF_Bw8pj-)f*LNKp`tP-t;0m0qlkXH6FQOS5Cq zM2>uLB+k`H2reiQCv)Qu0L~mioc6|{hj0Xm0}_b$#w{*4)|%gYZ{{~|-h1=LKQ8~e zSc;3qkid8Ivx~S`xL^8--nswF=IbLOUFn^Y5xpBEq4cG&dO-#W!*1t;-P*0V zmsZi=R_`cxK1wv5H$U@D^9B8UNzKCniUM39jG3APVXm`Vbk%&xmKSXV6IeiM5n$DL z&Th#E&4aN6BO92&-F{c|GgtcO^n?%inRiZ3Tq#bxfqUi;yn!Qw6$0q4kS054lmJJZ z6DtEN9T_$m6sll)?hD>B_*IMMD<=vregHiRRndIwt_{n$u!69P@FYO)HM;F~s?{18 zk*{WP0W-Y7CMZ2e|v671>>~L1jyrI zaNX7t=naO{ho1w|g@H2L1JFd%Pf3$XD%q*fY{VoPu@g1`*(d6MsX8Sfjo4}an^xl|GClp>)F0QuX_JNGAVKBer-s3eJ zx=dP$PPVSLx{bJ%T?1vpQ%@sj4mlOs?QH5waxcxadIqMa=Yv7bAO6Z)PK~JN!I~8D zGHO`AX-!oX%$qp%BEa#?#IZeGM%)a=(yP3M2bBKZW*yk*y-Aesz*1(PAjkU8@Fi*v z{ja0{aq=B|ve^~S*0Gl&p|EAu2Er!7O9(F`yaJGWaj%zjWbXBQ&@@TJr){JnWZAc3 z+h!W3)9dTo<~y-LXUzk#O*hPXP#!9L80r#wEi_tjmbDXjjMBay^&GCfhHwR8+J{!d z@fP0%}- za6}&o`&_1R*bp%I6t~(Qr<2=z4{mD<{z3MkINPwO-avR00r`*T@)X+E)7zjmVOUSX aQD{d6RW=_Mb{5fid>fhz=9|Jgt^Whj;})&} diff --git a/item.py b/item.py index 4dfffae..4c42e75 100644 --- a/item.py +++ b/item.py @@ -13,15 +13,6 @@ class Item(Resource): help="This field cannot be blank" ) - # TO GET ITEM WITH NAME - @jwt_required() - def get(self, name): - item = self.find_item_by_name(name) - if item: - return item - - return {"message": "item not found."}, 404 - # searches the database for items using name @classmethod def find_item_by_name(cls, name): @@ -42,6 +33,27 @@ def find_item_by_name(cls, name): } } + # method to insert an item into + @classmethod + def insert(cls, item): + connection = sqlite3.connect("./test/data.db") + cursor = connection.cursor() + + query = "INSERT INTO items VALUES (?, ?)" + cursor.execute(query, (item["name"], item["price"])) + + connection.commit() + connection.close() + + # TO GET ITEM WITH NAME + @jwt_required() + def get(self, name): + item = self.find_item_by_name(name) + if item: + return item + + return {"message": "item not found."}, 404 + # TO POST AN ITEM def post(self, name): # if there already exists an item with "name", show a messege, and donot add the item @@ -54,32 +66,31 @@ def post(self, name): "name": name, "price": data["price"] } - - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "INSERT INTO items VALUES (?, ?)" - cursor.execute(query, (item["name"], item["price"])) - - connection.commit() - connection.close() + try: + self.insert(item) + except: + return {"messege": "An error occured."} + return item, 201 # 201 is for CREATED status # TO DELETE AN ITEM def delete(self, name): - # use the items variable avalable globally - global items - # check if the item exists - item = next(filter(lambda x: x["name"] == name ,items), None) + # check if there exists any item by name: "name" + # if exists then delete it + if self.find_item_by_name(name): + connection = sqlite3.connect("./test/data.db") + cursor = connection.cursor() + + query = "DELETE FROM items WHERE name=?" + cursor.execute(query, (name,)) + + connection.commit() + connection.close() + return {"messege": "Item deleted"} + # if doesn't exist, skip deleting - if item is None: - return {"messege": "Item don't exist"}, 400 - - # store all the elements of items variable into local item - # except the one that was selected to be deleted - items = list(filter(lambda x: x["name"] != name, items)) - return {"messege": "Item deleted"} + return {"messege": "Item don't exist"}, 400 # TO ADD OR UPDATE AN ITEM def put(self, name): @@ -103,4 +114,14 @@ class ItemList(Resource): # TO GET ALL ITEMS def get(self): + items = [] + connection = sqlite3.connect("./test/data.db") + cursor = connection.cursor() + + query = "SELECT * FROM items" + for row in cursor.execute(query): + items.append({"name": row[0], "price": row[1]}) + + connection.commit() + connection.close() return {"items": items} \ No newline at end of file diff --git a/test/data.db b/test/data.db index 8edd7f0f3822d827500a1897594190c689202a4c..e7ccc2c6a658f4629b74699efe46a1aa2fca2c1c 100644 GIT binary patch delta 83 zcmZojXh@hK&B!@X#+i|GW5N=7E++oF4E*o;@A9A7EGTf0-%yYN83-^ji?b(ZBxV*l dXnsA^AEWV&pOIOVJt;pw+d===L-%ze)c}mC7V-c9 delta 50 zcmZojXh@hK&B!uQ#+i|2W5N=7Hb(yU4E*mm3kp2opBTU@$j`_u%AS;;pY5Rj>!JHP Gk!k>YD-V|d diff --git a/test/test.db b/test/test.db new file mode 100644 index 0000000000000000000000000000000000000000..fef2752436dc5b6d33dd3291e6afeca5141448ec GIT binary patch literal 12288 zcmeI$ze~eF6bJD8k*HPD6C`B4(Lxbw{j~^I2`E<3T9ATJQk&99n$sl3uKrQ}365_5 z37wn-K^z>s3v}+P@_q2$-MdEu`D~ZVi)NIEa-h;tkjpw*C6tl_DG4D=C)YU(syEiG z(W~j_1tS|*$By_SOei9hc$xPA<`94Y1Rwwb2tWV=5P$##AOL}XAaG3=Jn+Ln z{i3Z@*n+q3Q4%HnaFX4}`exq^#P`tys*xe#v+`I&JYp#D|!QSMjX32nav` z0uX=z1Rwwb2tWV=5P$##euF^Swy5XYH?jUbu)VXp=U5hXUF%j2lP%qsxf%0p6y?LZ zK5&>BvsA@{P2I0htF-3!RIjGHW&J(2m=f_VKE=Cu(^~`tAOHafKmY;|fB*y_009U< Y00Mtdz~+?NwyBn7D(9v$#(Amq18uZWrvLx| literal 0 HcmV?d00001 diff --git a/test/test.py b/test/test.py index eb1b92f..56eab91 100644 --- a/test/test.py +++ b/test/test.py @@ -1,17 +1,17 @@ import sqlite3 -connection = sqlite3.connect('./test/data.db') +connection = sqlite3.connect('./test/test.db') cursor = connection.cursor() create_table = "CREATE TABLE IF NOT EXISTS users (id int PRIMARY KEY, username text, password text)" cursor.execute(create_table) -user1 = (1, "bob", "1234") +# user1 = (1, "bob", "1234") -insert_query = "INSERT INTO users VALUES (?, ?, ?)" +# insert_query = "INSERT INTO users VALUES (?, ?, ?)" -cursor.execute(insert_query, user1) +# cursor.execute(insert_query, user1) users = [ (2, "rolf", "2345"), @@ -20,12 +20,14 @@ (5, "clint", "5678") ] -cursor.executemany(insert_query, users) +# cursor.executemany(insert_query, users) -select_query = "SELECT username, password FROM users" +select_query = "SELECT username, password FROM users where username='gold'" for row in cursor.execute(select_query): print(row) + + # commiting the changes to database connection.commit() # closing the connection to database From 933e106ff2a5c742bd10d40f8cb5ad7317db4921 Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Fri, 21 Jan 2022 17:08:05 +0530 Subject: [PATCH 12/16] minor changes --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index f714eb5..4a25664 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -./test/test.py -./test/test.db \ No newline at end of file +test/test.py +test/test.db \ No newline at end of file From 71f90dced10fe702c95396f19cfadbcb8136cace Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Fri, 21 Jan 2022 21:05:02 +0530 Subject: [PATCH 13/16] implemented database into put and get items --- __pycache__/item.cpython-39.pyc | Bin 3025 -> 3297 bytes item.py | 43 ++++++++++++++++++++++++-------- test/data.db | Bin 12288 -> 12288 bytes 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/__pycache__/item.cpython-39.pyc b/__pycache__/item.cpython-39.pyc index 97519cb561e2b0bfa7498383f9ca3c5baa2c3338..19f4cecd14bb21374652f2ff409d7da9b01d0d56 100644 GIT binary patch delta 1074 zcmZ{jO-vI(6vyYyessJ2pp=FWgLe5UZIFt}0S|~IHUU&(07GoRrePMWky59vCRkDv zxR`h$bJYY6#&Fh~C(kAth$n7%^y0;M)A-&NG@7`Z`R#oC_szUF@9no8b%gVwkj?N} z`1mFNHM|`@fQQ>hmq#t(7xot0glxbKZZZ)NL2nciAranU*|0a;BqH8ylV}!EoQ;T< zS(b{uo`SakQDtiHVNV@s-Tpm8w&5l+q~6&rDx$YSLiOuubxm8S_uaaAb$l-46e{j& z*_qAEIVD+Ga!1FU`H9R-#wq4kaUd=FKSGETx(J=WaT2%~}w>Q8X4!tTKi-(?%T#&)zC?7{}J#szdR!JqRD z9S_Q?OwO%`QK8rLT>v)E9@LH<(}a$W8GjrrCOxHbqAZ?-KojO)$~vp*=)Z5eaT`r| z8rh3j?;0;Uu9R!iSzB7FN>@0K?iTL5PN7(KWu;JDNy`-Jod4*&Yav<6ls>XLKsZbA z;zl8sJ*?gc5)Hge7^GeZkqtI3R^%v){>=-mRIQXyRVG^uY;J2D%%7%V0f#V{5W_Kj zqkP@+(gc5)PBkA|xg2F*E_Z0>a;s}XeYcV@pyK|4`0x5D>_X>qVyum!M%bg(TehK#CL{zaHkhJ8b2?P1@c;gy5h*V<$GQpqif zMv9oSkL+KNS<6Tlq=~K7roKtc@#-14tbG~pfg70 i2=`vl>`(adxJ~eS z^ZM9dcJ>nAf$tsVreZC^ySTkWTCn8s7z?nk~qc>s;6~DT| z{hW{1FBGylbUQ3ov-L)pU8tS932_n<4*NZhCnTTTjqBZ7Cg~jCKx3cQhL|*=a#}&y852 zQ1h$BLLssXh3YzQRFv)%3evIDFd?Vysi9Go+ElopFr_f9a7Dhb&u2zZWq4{PP__P; z76rQ(C8mSTScDU=m+e8kr fjuNN|V4BFuW#zNR=>K}?zD}eX0A08lYybcN delta 102 zcmZojXh@hK&B!@X#+i|GW5N=CHb(xB4E!HA3kqE3pV%NW`J=or7Zd+o2LAW_clpl% wg%9!@3Nj!A0VZZ~_T-Gj%pwQPuZQ|$G`{gOGK;b&<>zNR=>K}?zD}eX0NS!0dH?_b From 453932f64e66007a48c66f68405446d83bda4964 Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Fri, 21 Jan 2022 21:08:52 +0530 Subject: [PATCH 14/16] minor changes --- test/test.db | Bin 12288 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 test/test.db diff --git a/test/test.db b/test/test.db deleted file mode 100644 index fef2752436dc5b6d33dd3291e6afeca5141448ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12288 zcmeI$ze~eF6bJD8k*HPD6C`B4(Lxbw{j~^I2`E<3T9ATJQk&99n$sl3uKrQ}365_5 z37wn-K^z>s3v}+P@_q2$-MdEu`D~ZVi)NIEa-h;tkjpw*C6tl_DG4D=C)YU(syEiG z(W~j_1tS|*$By_SOei9hc$xPA<`94Y1Rwwb2tWV=5P$##AOL}XAaG3=Jn+Ln z{i3Z@*n+q3Q4%HnaFX4}`exq^#P`tys*xe#v+`I&JYp#D|!QSMjX32nav` z0uX=z1Rwwb2tWV=5P$##euF^Swy5XYH?jUbu)VXp=U5hXUF%j2lP%qsxf%0p6y?LZ zK5&>BvsA@{P2I0htF-3!RIjGHW&J(2m=f_VKE=Cu(^~`tAOHafKmY;|fB*y_009U< Y00Mtdz~+?NwyBn7D(9v$#(Amq18uZWrvLx| From 68588800f1b924b92db8285501ebf4375745bf10 Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Mon, 24 Jan 2022 18:56:54 +0530 Subject: [PATCH 15/16] made seperate folders for item and user --- __pycache__/security.cpython-39.pyc | Bin 602 -> 593 bytes app.py | 4 +- database.py | 3 + models/__init__.py | 0 models/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 154 bytes models/__pycache__/item.cpython-39.pyc | Bin 0 -> 1517 bytes models/__pycache__/user.cpython-39.pyc | Bin 0 -> 1182 bytes models/item.py | 48 +++++++ models/user.py | 44 ++++++ requiements.txt | 3 +- resources/__init__.py | 0 resources/__pycache__/__init__.cpython-39.pyc | Bin 0 -> 157 bytes resources/__pycache__/item.cpython-39.pyc | Bin 0 -> 2493 bytes resources/__pycache__/user.cpython-39.pyc | Bin 0 -> 1152 bytes item.py => resources/item.py | 79 ++--------- user.py => resources/user.py | 129 ++++++------------ security.py | 6 +- test/data.db | Bin 12288 -> 12288 bytes 18 files changed, 159 insertions(+), 157 deletions(-) create mode 100644 database.py create mode 100644 models/__init__.py create mode 100644 models/__pycache__/__init__.cpython-39.pyc create mode 100644 models/__pycache__/item.cpython-39.pyc create mode 100644 models/__pycache__/user.cpython-39.pyc create mode 100644 models/item.py create mode 100644 models/user.py create mode 100644 resources/__init__.py create mode 100644 resources/__pycache__/__init__.cpython-39.pyc create mode 100644 resources/__pycache__/item.cpython-39.pyc create mode 100644 resources/__pycache__/user.cpython-39.pyc rename item.py => resources/item.py (54%) rename user.py => resources/user.py (50%) diff --git a/__pycache__/security.cpython-39.pyc b/__pycache__/security.cpython-39.pyc index c398288b90f32042c7a50f6440c0306b27b74392..211b4693ecb25d635c2e170c05788150878eb2e4 100644 GIT binary patch delta 80 zcmcb`a*>5Mk(ZZ?0SJ<$-z3hT$eYf^8CslLL{nNQYde8n5ZoeNS`tXB%uFjg`k0>kI85<&E15P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!H$er{fgzLTq= ztFfi48;Eo?a5L8rD9X=DO)e?c52!53$j=LM4Gu{x$kflxPf5)w){l?R%*!l^kJl@x Tyv1Py6fDh2wF4Ra8HgDGVZ0*% literal 0 HcmV?d00001 diff --git a/models/__pycache__/item.cpython-39.pyc b/models/__pycache__/item.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02879b2989df6bd7942663bc597f816ed474d5d4 GIT binary patch literal 1517 zcmchXOK;RL5P)sxvFY}~Q{p8=E(n597sLS&^aZ3)36`q6fV7uriM=9KHfimwpsV!M z9udEQ!|t(v$yZKX_yL@lah4Ve;)o@WC!Vo0{$}j%>};Jt3qF49ey|Dof*-#&3qF>i ztBW8w;WQ;3@|1AKt$o6+J=UR|wn$)q1v_cRD1U8->+iv=AmB|pj8o3`Nyp+Aw_&t} z!yWGKlResTd5wE8SL0K>4x`7XVfPt5wN{A!i=2xz#w~v~)EV^0(A7y0B`rxrN(K^s z1xso3fN4AH_Jww~WD<+O(zX(5Pr`ADbU+*sS%cyGgGN6q8jr%;;hp>8D$12xt9Kjg zGT#(&p&IKu#k)M)2wUy$R?_HWFshM2T=QEy+KZwjONuDM9To0Ps7r^Z596Ny=@3&i zP8#ZX2y=irP)f3i9jJb05I$>4G#e36>7tIoR>A{K+nXxSra)6jg3#gI(Ld1?n`tyb z!?hTk`QH;z3NnI!jp;5c*@%tFuEp7|U0Nfnv`gBfW47y*&d3If3m(pxP*S>bxdizM z02|0w^ZVRX<)s2@ge8i;uH_yV2(8pvfECsHvsqGXD zcXTbzvkVw(Hy%ipOI;HmL_8>j_Ijd-fjVR_PID!KnzrIpndIsEWLc7D64_~Idm!YF zcBN2*w9uB!-yf%Ss+VLu!f>LuI}wI53oA|S5LTxiv*{f3aAdN=G#uCp_ge>@vKv)@+3vZGWxVemOz- zdgb}6u;pK0y6G!gz=D@DX=ggt=S=5eIlbd8p z$l@}X6z)xE1?4P28J;`>Qn~#X3RhpPKUryq69BES?VF3du=IO9{hbA-r2=vuH3T6q zpg4Z+!4{ORxCW+wp1X2u22*(Bv3#OP*P{qtgF%Y=OcZSox@l#Rcr7KquzEU9yGr#1 zJRw}3!)bg`5;>># zi1-c3v43f=oVf4ito?TEdF;%$<8XeyMnLwy{0I+CLcZb4v>5R60+w0^ z;DpnJw8?A288?mzH;!1Fa=Jqr=6A4@R)jb$llc4aRS@tdZN@2Q$E0ltlN;PTCP%bw zfo^fT(rxZQMpw`5DIqsAE|LgJn+WO*);cV89iXHo2}sERX=wm5P9OnoH4M#SuH6Fi zq+wTR_aId2Fq6DtYEy}%qm3Zu5;IB*;DksQw$rCxH_g3Q{zHG|vA==%^1;Rhu+p*B2&#YsQSbC(DkITt({ zOQ{-r3rbE#!0wn1S;t9&R^fH->YwIzu&B5`KtcmjlbBda-Hym3U_@vuN-`zj@{A}^6|uVZD=f}Zc?r7G zR<97UuWcz*k>uKt*`YS^_=@~9m_f(OojB#eem_7X)`PREmH-H=QJ0x?fw|OVHDHLI5?z8Xb|XH5WoNz3F>n}&?~~^%p#F(JsTzP&vXS0JeN1Ij9Zgh u{;W#kEaU&KFwkYL#c1scqt*8Ylk*sdK2zOP8LGQ>pPg0loMHxabJkPmE literal 0 HcmV?d00001 diff --git a/models/item.py b/models/item.py new file mode 100644 index 0000000..8e8f0ff --- /dev/null +++ b/models/item.py @@ -0,0 +1,48 @@ +import sqlite3 + +class ItemModel: + + def __init__(self, name, price): + self.name = name + self.price = price + + def json(self): + return {"name": self.name, "price": self.price} + + # searches the database for items using name + @classmethod + def find_item_by_name(cls, name): + connection = sqlite3.connect('./test/data.db') + cursor = connection.cursor() + + query = "SELECT * FROM items WHERE name=?" + result = cursor.execute(query, (name,)) + + row = result.fetchone() + connection.close() + + if row: + # return cls(row[0], row[1]) + return cls(*row) # same as above + + # method to insert an item into + def insert(self): + connection = sqlite3.connect("./test/data.db") + cursor = connection.cursor() + + query = "INSERT INTO items VALUES (?, ?)" + cursor.execute(query, (self.name, self.price)) + + connection.commit() + connection.close() + + def update(self): + connection = sqlite3.connect("./test/data.db") + cursor = connection.cursor() + + query = "UPDATE items SET price=? WHERE name=?" + cursor.execute(query, (self.price, self.name)) + + connection.commit() + connection.close() + diff --git a/models/user.py b/models/user.py new file mode 100644 index 0000000..18263db --- /dev/null +++ b/models/user.py @@ -0,0 +1,44 @@ +import sqlite3 + +class UserModel: + + def __init__(self, _id, username, password): + self.id = _id + self.username = username + self.password = password + + @classmethod + def find_by_username(cls, username): + connection = sqlite3.connect('./test/data.db') + cursor = connection.cursor() + + query = "SELECT * FROM users WHERE username=?" + result = cursor.execute(query, (username,)) # parameters must be in the form of tuple. + + row = result.fetchone() + if row: + # user = cls(row[0], row[1], row[2]) + user = cls(*row) # is similar to passing all values of row + else: + user = None + + connection.close() + return user + + @classmethod + def find_by_id(cls, _id): + connection = sqlite3.connect('./test/data.db') + cursor = connection.cursor() + + query = "SELECT * FROM users WHERE id=?" + result = cursor.execute(query, (_id,)) # parameters must be in the form of tuple. + + row = result.fetchone() + if row: + # user = cls(row[0], row[1], row[2]) + user = cls(*row) # is similar to passing all values of row + else: + user = None + + connection.close() + return user diff --git a/requiements.txt b/requiements.txt index aaa2275..16bcdb4 100644 --- a/requiements.txt +++ b/requiements.txt @@ -1,3 +1,4 @@ Flask Flask-RESTful -Flask-JWT \ No newline at end of file +Flask-JWT +Flask-SQLAlchemy \ No newline at end of file diff --git a/resources/__init__.py b/resources/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/resources/__pycache__/__init__.cpython-39.pyc b/resources/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fbe2f604657164d0db3d87cbaf02e08d2447230a GIT binary patch literal 157 zcmYe~<>g`k0@>%U5<&E15P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!HMer{fgzLTq= ztFfi48;Eo?a5L8rD9X=DO)e?c52!53$j=LM4Gu{x$kZ=NEzU13N=_}-kB`sH%PfhH Y*DI*J#bJ}1pHiBWY6mj=GY~TX0MO7RMgRZ+ literal 0 HcmV?d00001 diff --git a/resources/__pycache__/item.cpython-39.pyc b/resources/__pycache__/item.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d96291831ed16e4a7059604a3d187fcc2208617f GIT binary patch literal 2493 zcmZ`*&2Jk;6rY*>^u|t;wv@J%vZc`C0(Pq&5E7J>)`3cGsFH}PD`Y%abQa)N91JI%rX<2AOKHX;mRXTSv2Uez=0r~BMy~1Gsh9bYZ`w{;%YrDN z3H+F49v^+bD8Yz>7fVZ>h+su;?i z&^`iXu>vWrfM6dd}sd!@)86kMb|Tx$Aqp|b$DS_UIXL^+9=u=eZ;i5%f< zx||A+Gj4JFN1GDi?-K5C_c__6QH^`te@>#njMjKyMrZg8ufu4aHz4>~ZR5waGmuG7 ztd7pFZX_z~CnDuxFV6F#4A(@smd5#$rlsw2dr)n~gs$xkkq&wcLOZ-HXyAPZZuKsh zlI+njozNXNX7bFK?Xd}2fwXXzP;T`Z#9%LJFB3||>tb{wfoMYfY`+-hyp{Y+A=#Gn zU@1M{PjcQxkM7!bH;*%+?M+qW7?~1jU)$9fdi+l0DR}3_t#+1|?JqkwIyXPa&r552s=3 z*yfRYm@u>X4QL#0US7lvkLfSKyWcF>xQ!bx*``V44lBu+jv05(kzKZ9jp}1-&zTTP z9+CVkg(t9*au?q7`phMd0l@17eB24}(Lh)`fKUL04u&3%PK0qPMa;KD@hnlL+W!fV zlr@NIG=Dn}g_MO1i(YRC9Bl3X4U_wSz+}@iSj$;xOWd<|4Q-_k%(ENIb*0@TS3;KZ z1ioR*Idq;!XPd`mEKgz|QLD^pGczbuc>!7qXA#NMEMT*Y(K>bMNj5SnXrb3JP#tha zU=66Kf+J8DOSWh618$)rb}Y_zYy@v?k7=Jy7$v|sfXO^Pe4&|i~M2da>g**e1jOs{(5Oga_!AEmd zugI^K73T6yaBBLm0M(w_N@1~^+Upg04g}OLBtR8Xd*Yes4NCz7MV2L{c6w<6)xwzq zH#m4HDRPP0(hk%ax&1oQZWYkS;89_12Q&cI+H{ur6n@rd219LCe*Z%Ih{E5)3MJX3 zs97K>kku&JDlJ1-YUm1hb221y8E9)C(st|F0d1i&Rdhe3ZGOf0nVd|~8_0j$57vTw zL3MDK3~6Npf*DT-Tb@Vr78F_af-z2b|vaTHL9scyFv26op}yD24n>V0DI3{$sBCL&Pv~9p-Gv=zOo5LM zx6To;_BlBBeq|F%$<}+IdBw&s8e_D|a_w_FK3WX2Q25_L~h8J#qp5mq?tE z78uuo1=5I&gyLL!9NawCl&wz literal 0 HcmV?d00001 diff --git a/resources/__pycache__/user.cpython-39.pyc b/resources/__pycache__/user.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d3874b63e234027f8cd01369e05f477aa27e3b86 GIT binary patch literal 1152 zcmYjQ&2Aev5GJ|5mZiWgdT^2+_Rs=VQAllbND2f=+(Ib=xT+z^J?v$%UXHAF_eUnV zNF>;&=GX##1nHPZ=_~NsQ!aUcpoh+^Z9v@RaA$Ug^UcR$+Us=~j_?2ckY0O?{Y%R3 za8Y@IQ$Il=ndAkFX%z)8MJ!4ub~x!y;g(+ParQHluJqnA>4EseiG9hZtna_aXg2N( z8%{vijmp4=3NDwa($MF2?^J{OrIt`+Hg(%)>^z>i}Ypimc^kA5y+nHQmP4@=h}d>VS`$gmM~jCm@RT0&2uPZl%-Wwo9GN8 zD3@l{cdTnx%Nxv1u0UFM0magW%T(*vwUQY}baw-JWCZ&soVr3`*ahE+ExYChfnRaS z@3SpeUl8n^OLs1&%y=7LdRu-iuEZulUq|}a?v=9%uWlnSF1XL;Vk+>*AA^R zlzX^Shj!}kj}@i2K?z!?=dk|zsEVl2=yh%uky)gsRjKYMEfl136~P;1L=W=6v6A(@ z!O(ydPojsW6l}yf7$=wmzKwlQQ zfk!sT>Z*dwSU+o&u9Xeo4P=c0G}L988|!67jh*FLS3@zkE)`-sw_$l*sZS||ciDhi zy<_SDY9F5s%gPLY9DO%>^uy>S$)j&yJ|3Q^`T}$5;mOJ@>S{8Y&eCN*RJVPshlFpi zTv>NnYjcP@>CaFw-Vygi*X@W)8*~0s7hAyh!!$2^MVd{FFdj3&-vwRw(p<2x!l&4ckddv?|JM!>2cO PJ)?V~sXIe{z`NpqV+k(R literal 0 HcmV?d00001 diff --git a/item.py b/resources/item.py similarity index 54% rename from item.py rename to resources/item.py index 9a4c81d..e70727a 100644 --- a/item.py +++ b/resources/item.py @@ -4,6 +4,8 @@ from flask_restful import Resource, reqparse from flask_jwt import jwt_required +from models.item import ItemModel + class Item(Resource): parser = reqparse.RequestParser() @@ -12,89 +14,39 @@ class Item(Resource): required=True, help="This field cannot be blank" ) - - # HELPER METHODS---------------------------- - # searches the database for items using name - @classmethod - def find_item_by_name(cls, name): - connection = sqlite3.connect('./test/data.db') - cursor = connection.cursor() - - query = "SELECT * FROM items WHERE name=?" - result = cursor.execute(query, (name,)) - - row = result.fetchone() - connection.close() - - if row: - return { - "item": { - "name": row[0], - "price": row[1] - } - } - - # method to insert an item into - @classmethod - def insert(cls, item): - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "INSERT INTO items VALUES (?, ?)" - cursor.execute(query, (item["name"], item["price"])) - - connection.commit() - connection.close() - - - @classmethod - def update(cls, item): - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "UPDATE items SET price=? WHERE name=?" - cursor.execute(query, (item["price"], item["name"])) - - connection.commit() - connection.close() - - # HELPER METHODS----------------------------X # TO GET ITEM WITH NAME @jwt_required() def get(self, name): - item = self.find_item_by_name(name) + item = ItemModel.find_item_by_name(name) if item: - return item + return item.json() return {"message": "item not found."}, 404 # TO POST AN ITEM def post(self, name): # if there already exists an item with "name", show a messege, and donot add the item - if self.find_item_by_name(name): + if ItemModel.find_item_by_name(name): return {"messege": f"item {name} already exists"} ,400 data = Item.parser.parse_args() # data = request.get_json() # get_json(force=True) means, we don't need a content type header - item = { # flask will look into the content, and format the data. - "name": name, - "price": data["price"] - } + item = ItemModel(name, data["price"]) try: - self.insert(item) + item.insert() except: return {"messege": "An error occured."}, 500 - return item, 201 # 201 is for CREATED status + return item.json(), 201 # 201 is for CREATED status # TO DELETE AN ITEM @jwt_required() def delete(self, name): # check if there exists any item by name: "name" # if exists then delete it - if self.find_item_by_name(name): + if ItemModel.find_item_by_name(name): connection = sqlite3.connect("./test/data.db") cursor = connection.cursor() @@ -112,26 +64,23 @@ def delete(self, name): def put(self, name): data = Item.parser.parse_args() # data = request.get_json() - item = self.find_item_by_name(name) + item = ItemModel.find_item_by_name(name) - updated_item = { - "name": name, - "price": data["price"] - } + updated_item = ItemModel(name, data["price"]) # if item is not available, add it if item is None: try: - self.insert(updated_item) + updated_item.insert() except: return {"message": "An error occured while inserting."}, 500 # if item exists, update it else: try: - self.update(updated_item) + updated_item.update() except: return {"message": "An error occured while updating."}, 500 - return updated_item + return updated_item.json() class ItemList(Resource): diff --git a/user.py b/resources/user.py similarity index 50% rename from user.py rename to resources/user.py index dcca8df..379de51 100644 --- a/user.py +++ b/resources/user.py @@ -1,87 +1,44 @@ -import sqlite3 -from flask_restful import Resource, reqparse - -class User: - - def __init__(self, _id, username, password): - self.id = _id - self.username = username - self.password = password - - @classmethod - def find_by_username(cls, username): - connection = sqlite3.connect('./test/data.db') - cursor = connection.cursor() - - query = "SELECT * FROM users WHERE username=?" - result = cursor.execute(query, (username,)) # parameters must be in the form of tuple. - - row = result.fetchone() - if row: - # user = cls(row[0], row[1], row[2]) - user = cls(*row) # is similar to passing all values of row - else: - user = None - - connection.close() - return user - - @classmethod - def find_by_id(cls, _id): - connection = sqlite3.connect('./test/data.db') - cursor = connection.cursor() - - query = "SELECT * FROM users WHERE id=?" - result = cursor.execute(query, (_id,)) # parameters must be in the form of tuple. - - row = result.fetchone() - if row: - # user = cls(row[0], row[1], row[2]) - user = cls(*row) # is similar to passing all values of row - else: - user = None - - connection.close() - return user - -# New user registraction class -class UserRegister(Resource): - # Creating a request parser - parser = reqparse.RequestParser() - # Adding username argument to parser - parser.add_argument( - "username", - type=str, - required=True, - help="This field cannot be empty" - ) - # Adding password argument to parser - parser.add_argument( - "password", - type=str, - required=True, - help="This field cannot be empty" - ) - - # calls to post a new user (new user registration) - def post(self): - data = UserRegister.parser.parse_args() - # First check if that user is present or not - if User.find_by_username(data["username"]): - # if exists, then don't add - return {"message": "An user with that username already exists."}, 400 - - # else...continue - # 1. Connect to database - connection = sqlite3.connect('./test/data.db') - # 2. Create database cursor - cursor = connection.cursor() - # 3. SQL query to inser new useer information - query = "INSERT INTO users VALUES (NULL, ?, ?)" - - cursor.execute(query, (data["username"], data["password"])) - # 4. Commit the changes and close the connection to database - connection.commit() - connection.close() - +import sqlite3 +from flask_restful import Resource, reqparse +from models.user import UserModel +# New user registraction class +class UserRegister(Resource): + # Creating a request parser + parser = reqparse.RequestParser() + # Adding username argument to parser + parser.add_argument( + "username", + type=str, + required=True, + help="This field cannot be empty" + ) + # Adding password argument to parser + parser.add_argument( + "password", + type=str, + required=True, + help="This field cannot be empty" + ) + + # calls to post a new user (new user registration) + def post(self): + data = UserRegister.parser.parse_args() + # First check if that user is present or not + if UserModel.find_by_username(data["username"]): + # if exists, then don't add + return {"message": "An user with that username already exists."}, 400 + + # else...continue + # 1. Connect to database + connection = sqlite3.connect('./test/data.db') + # 2. Create database cursor + cursor = connection.cursor() + # 3. SQL query to inser new useer information + query = "INSERT INTO users VALUES (NULL, ?, ?)" + + cursor.execute(query, (data["username"], data["password"])) + # 4. Commit the changes and close the connection to database + connection.commit() + connection.close() + return {"messege": "User added successfully."}, 201 \ No newline at end of file diff --git a/security.py b/security.py index d8db52d..9fb76aa 100644 --- a/security.py +++ b/security.py @@ -1,12 +1,12 @@ from werkzeug.security import safe_str_cmp -from user import User +from models.user import UserModel def authenticate(username, password): - user = User.find_by_username(username) + user = UserModel.find_by_username(username) # if user and user.password == password: if user and safe_str_cmp(user.password, password): return user def identity(payload): # payload is the contents of jwt user_id = payload["identity"] - return User.find_by_id(user_id) + return UserModel.find_by_id(user_id) diff --git a/test/data.db b/test/data.db index 0e8e31df11f997bfb3bfade14b265bb42b48e6c6..c352345b1eca5906bb3c44aada19a42e31165bc3 100644 GIT binary patch delta 132 zcmZojXh@hK&B!@X##xY)K`-2kmw|zSi9d#ce;$9#W>|!XPeMoSRvakyxCP#?8pWAS{}cpJZrcYy#1Jmx2E-|9hZ@i~Pz0Ow8i!$%z@6 ZMGo4(9=fj+spe;97G+P$&(DSl007$8B%}ZU delta 147 zcmZojXh@hK%_uZc##vB^K`-2cmw|zSi9d#ce;$9#WRL3!XPY~l%Hg1WNgCA$ig5l8l0P1k^$xdbu;q6XW)MiglB WfuEUKlszdwKifh7*F*PpBGmw^79QUK From 815d0b0b3e9c292269b9a8ffdd065709c57d985b Mon Sep 17 00:00:00 2001 From: Subhadeep Date: Tue, 25 Jan 2022 17:20:22 +0530 Subject: [PATCH 16/16] Added Store functions --- README.md | 18 +++++- __pycache__/database.cpython-39.pyc | Bin 0 -> 191 bytes app.py | 14 +++++ create_tables.py | 13 ----- {test => database}/data.db | Bin 12288 -> 16384 bytes models/__pycache__/item.cpython-39.pyc | Bin 1517 -> 1507 bytes models/__pycache__/store.cpython-39.pyc | Bin 0 -> 1559 bytes models/__pycache__/user.cpython-39.pyc | Bin 1182 -> 1204 bytes models/item.py | 65 +++++++++------------ models/store.py | 33 +++++++++++ models/user.py | 47 +++++---------- requiements.txt => requirements.txt | 6 +- resources/__pycache__/item.cpython-39.pyc | Bin 2493 -> 2226 bytes resources/__pycache__/store.cpython-39.pyc | Bin 0 -> 1521 bytes resources/__pycache__/user.cpython-39.pyc | Bin 1152 -> 979 bytes resources/item.py | 53 ++++++----------- resources/store.py | 38 ++++++++++++ resources/user.py | 14 +---- test/test.py | 34 ----------- 19 files changed, 168 insertions(+), 167 deletions(-) create mode 100644 __pycache__/database.cpython-39.pyc delete mode 100644 create_tables.py rename {test => database}/data.db (71%) create mode 100644 models/__pycache__/store.cpython-39.pyc create mode 100644 models/store.py rename requiements.txt => requirements.txt (93%) create mode 100644 resources/__pycache__/store.cpython-39.pyc create mode 100644 resources/store.py delete mode 100644 test/test.py diff --git a/README.md b/README.md index 1331531..3661f3e 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,20 @@ Contains <> branches Final and stable application is in the master branch -Use a virtual environment with python 3.9 to run the application \ No newline at end of file +NOTE: Use a virtual environment with python 3.9 to run the application + +## INSATLLATION + +Run the following command to install dependencies: + +``` +pip install -r requirements.txt +``` + +## RUN + +Run the following command to start the application: + +``` +python app.py +``` \ No newline at end of file diff --git a/__pycache__/database.cpython-39.pyc b/__pycache__/database.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ee989203d66d4a73022f0709e7b44a88769b5ec5 GIT binary patch literal 191 zcmYe~<>g`kf`2pKC0YUL#~=I;5=#=35{pyy3My}L*yQG?l;)(`F#>fK JgG}OK0sz7iE&l)j literal 0 HcmV?d00001 diff --git a/app.py b/app.py index 9c07fb1..e475db3 100644 --- a/app.py +++ b/app.py @@ -5,13 +5,24 @@ from security import authenticate, identity from resources.user import UserRegister from resources.item import Item, ItemList +from resources.store import Store, StoreList +from database import db app = Flask(__name__) +app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database/data.db" + +app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False # turns of flask_sqlalchemy modification tracker app.secret_key = "komraishumtirkomchuri" api = Api(app) +@app.before_first_request +def create_tables(): + db.create_all() + # above function creates all the tables before the 1st request is made + # unless they exist alraedy + # JWT() creates a new endpoint: /auth # we send an username and password to /auth # JWT() gets the username and password, and sends it to authenticate function @@ -21,8 +32,11 @@ jwt = JWT(app, authenticate, identity) api.add_resource(Item, '/item/') +api.add_resource(Store, '/store/') api.add_resource(ItemList, '/items') +api.add_resource(StoreList, '/stores') api.add_resource(UserRegister, '/register') if __name__ == "__main__": + db.init_app(app) app.run(port=5000, debug=True) \ No newline at end of file diff --git a/create_tables.py b/create_tables.py deleted file mode 100644 index 6afb122..0000000 --- a/create_tables.py +++ /dev/null @@ -1,13 +0,0 @@ -import sqlite3 - -connection = sqlite3.connect('./test/data.db') -cursor = connection.cursor() - -create_table = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username text, password text)" -cursor.execute(create_table) - -create_table = "CREATE TABLE IF NOT EXISTS items (name text, price real)" -cursor.execute(create_table) - -connection.commit() -connection.close() \ No newline at end of file diff --git a/test/data.db b/database/data.db similarity index 71% rename from test/data.db rename to database/data.db index c352345b1eca5906bb3c44aada19a42e31165bc3..b6cbb4bbceed794716e955ad0182f81d0283c66b 100644 GIT binary patch literal 16384 zcmeI&J#W)M7zgk>JH zd9LNTN_yV-v(Kx6E9y=5aP*=0kbZlgS!dSGyh4Hi1Rwwb2tWV=5P$##AOL|i7Fg}+ zhHcyY<9HcP-bMMHa*?T`)|0{w1O@IhPml^xt8T_K8v2142uc1ZApf=J-KV;F94;by ztOEHuMzHu-8-ZND5UOZ~zDs!9KKg3H^hJF6R9ajoWRz0)j8 zGgW98R#TxXxQg+Al7(4zmZY=Glz(rexSMn9JIfy=2tWV=5P$##AOHafKmY;|fB*!p zkH9TnV|N>qWYXU0JSpz~n)Q`gKk@+)l+kUz!5W4+Ns@W@Q5pILLW!f3 delta 284 zcmZo@U~EX3AT7wrz`(!^#4x}#QO6i4s2A?V3lw7Fk73}S#~-sJ5aj9W7!;}C?HZ}0P+FW?gseZYxVSvOCmAD3?LHK8T|k0v z@v;5~Jy=Kop&WS4$*0_V$_&>JHSsYNI2>|@+;3*SQ8E~G8IJzD56RPjvG=su96oLy z<1{~_00z8ZC6760zcUcvoiXqf&&69W_Q0RANpOXJY{IR8hk8S5gqso^xsKN#rs^%32(VOe6 zO!Pwjr50C*2>ME(KtpG)RhpTsu9h9s)LNPS4C3yTRQE_qiMtu3)5Rw^%>xuGzG9NC z1WLa0PzqpEcF7MWp7pDwR5rjbr^-g|ahbuyx4u!uOjEgZk3=8ECDYru{P*+IUycrS zovXAlM~92%bzS}WZ2BshXGbN)WR57N{rSR1Qf5`wNV$Xe3{`~j5P!?jZ36ahTvATv z>p?m)WFrWcvlYuRlpF)eJ>dTm1H{3lZ$$E4=gY^y2L9W+mTP0`scqYQD&dI^9H)4D9PM(?5N)65M`^0$&rEg@-=R(8)ON z@jhQZyhHk_j-g^<#A zr9@Jn7Nqy3d~=!<*Oq~ln1({N+cufule#!9E4%fgYSf9+nmA*_X`{31#8ux0&x<-~ zTvyrdb8O-4r20cG9D{9Nt0HNz8s>F2w}ER&J)~HPv9^~Mi7}abBP z$1mc#CO*(K#HdL4-jEOZNQ`+`L_y>W-VGz)c^zQSM>lnCV+q`Ui?iPMxQ%{o6Z0E2 JtD|dQd<0LJSdjn# literal 1517 zcmchXOK;RL5P)sxvFY}~Q{p8=E(n597sLS&^aZ3)36`q6fV7uriM=9KHfimwpsV!M z9udEQ!|t(v$yZKX_yL@lah4Ve;)o@WC!Vo0{$}j%>};Jt3qF49ey|Dof*-#&3qF>i ztBW8w;WQ;3@|1AKt$o6+J=UR|wn$)q1v_cRD1U8->+iv=AmB|pj8o3`Nyp+Aw_&t} z!yWGKlResTd5wE8SL0K>4x`7XVfPt5wN{A!i=2xz#w~v~)EV^0(A7y0B`rxrN(K^s z1xso3fN4AH_Jww~WD<+O(zX(5Pr`ADbU+*sS%cyGgGN6q8jr%;;hp>8D$12xt9Kjg zGT#(&p&IKu#k)M)2wUy$R?_HWFshM2T=QEy+KZwjONuDM9To0Ps7r^Z596Ny=@3&i zP8#ZX2y=irP)f3i9jJb05I$>4G#e36>7tIoR>A{K+nXxSra)6jg3#gI(Ld1?n`tyb z!?hTk`QH;z3NnI!jp;5c*@%tFuEp7|U0Nfnv`gBfW47y*&d3If3m(pxP*S>bxdizM z02|0w^ZVRX<)s2@ge8i;uH_yV2(8pvfECsHvsqGXD zcXTbzvkVw(Hy%ipOI;HmL_8>j_Ijd-fjVR_PID!KnzrIpndIsEWLc7D64_~Idm!YF zcBN2*w9uB!-yf%Ss+VLu!f>LuI}wI53oA|S5LTxiv*{f3aAdN=G#uCp_ge>@vKv)@+3vZGWxVemOz- zdgb}6u;pK0y6G!gz=D@DX=ggt=S=5eIlbd8p z$l@}X6z)xE1?4P28J;`>Qn~#X3RhpPKUryq69BES?VF3du=IO9{hbA-r2=vuH3T6q zpg4Z+!4{ORxCW+wp1X2u22*(Bv3#OP*P{qtgF%Y=OcZSox@l#Rcr7KquzEU9yGr#1 zJRw}3!)bg`8u~N>;x^^6iu6Uxy8sF7)F7lC^A$qs!RtL#Q7fOoWi@4$#Ve- z$`r2|y0?Hd`j6>9z_nAR4&6HSJzfi&sC_WW$f+T=&%;MHN^kXr10?sm0w+9AjE}NpF zSi*rN0(cUraN0s?)0J;U(ox|G_p1oPHDB{&2W?$wK^r<~?Lh=PS1jp67kao3)GqX4 zaK+y6WDj;>55Emz2>ZD1!vTW2=epy%GU~?)ly+@Px_yBldoz<4shP`HYX0s7LAjmh zwJI9F4$RB6$TRc{b-I{mVk;NYNuHuuqHxKVOd>;LcFjlEcm&U?Sh&zCJu!XsxMpS- zmw)1CPfkxvHC0({PfzCc%c}h8`|*o(mY)^`(4KmLhqJkhq|D2_mU2L0e0;vRcazKE z#-4F>*bLH%YLD$JRF-T?!hwUhB2BDF;Q{&*o8T==MBxYhi6^)NawcBs$zD$kNdw-*y5Y5Bww#TS!yyL)$96WcfMK{|xG@syU|H*ucnhR2`uel+9ZpAeeY>2YqZSPjdkLnqq zv*+vp72<4)2?Kx2S7MD^#A0N6XhB%5i%VtZZfBC~S{ZpZcdbcoY>hMonYIl+D)tr) z`;)u`Nok;Iet(as_uKFpW~)RoGYBB9gcX^NE1A1aq3n^V!N_>Bpn)JSu7niC2 z&oYn_iO{OqHgvY1R{F9iUFUgOt8-<1W4iXZHhFp8^laZKoz_UXeVNaEyBg|8-D1an;qwRcC4GKG)3-F;bdJ~P6&WfyiGPog2!kOXid_)}Q7Cw~9fjUw6o)R_l&t~U X@_#dLz3XBZ9W_}WQ)Bsd?2CT^tT1AS literal 0 HcmV?d00001 diff --git a/models/__pycache__/user.cpython-39.pyc b/models/__pycache__/user.cpython-39.pyc index 29d906712cc7e27ac853657cc95557b1341d66ff..de3c6aae46d3ea161ed52e57528f14dfa6b2ad96 100644 GIT binary patch literal 1204 zcmbVLy>1gh5Z<3V`}~)fC=}!gIEplM2%$&;Aqt`>4$aEa>Tgjm$Z2Y zyUauIB3sZ{l8V+w+y);SH$-$)7n%^=(nI<`CHI|E}m~g z4>4`o)+eL%#{yI;{3*KTG^C<4(McBRnf$C~_s0k*=4fhhJ~oCNqMAOMIh_+p<_s;u z9*{eF6fzsQ>+&d5Hkd@ld@VGD+AbMA#w2;Z)G>xb-imO3y@Vl%%E7@@!`PQKC(Wh4DBws|peN#s;Ex{Zs-^*RbsVjU|DYVn!{_ ze`wbp1|>FYffHU*y7KvwP^A5UXh+@9)2>e2G|HHy$SscmL?bS;EGe<80UmCG>zn9{ zl4T(wDx5;>># zi1-c3v43f=oVf4ito?TEdF;%$<8XeyMnLwy{0I+CLcZb4v>5R60+w0^ z;DpnJw8?A288?mzH;!1Fa=Jqr=6A4@R)jb$llc4aRS@tdZN@2Q$E0ltlN;PTCP%bw zfo^fT(rxZQMpw`5DIqsAE|LgJn+WO*);cV89iXHo2}sERX=wm5P9OnoH4M#SuH6Fi zq+wTR_aId2Fq6DtYEy}%qm3Zu5;IB*;DksQw$rCxH_g3Q{zHG|vA==%^1;Rhu+p*B2&#YsQSbC(DkITt({ zOQ{-r3rbE#!0wn1S;t9&R^fH->YwIzu&B5`KtcmjlbBda-Hym3U_@vuN-`zj@{A}^6|uVZD=f}Zc?r7G zR<97UuWcz*k>uKt*`YS^_=@~9m_f(OojB#eem_7X)`PREmH-H=QJ0x?fw|OVHDHLI5?z8Xb|XH5WoNz3F>n}&?~~^%p#F(JsTzP&vXS0JeN1Ij9Zgh u{;W#kEaU&KFwkYL#c1scqt*8Ylk*sdK2zOP8LGQ>pPg0loMHxabJkPmE diff --git a/models/item.py b/models/item.py index 8e8f0ff..987a584 100644 --- a/models/item.py +++ b/models/item.py @@ -1,48 +1,37 @@ -import sqlite3 +from database import db -class ItemModel: +class ItemModel(db.Model): # tells SQLAlchemy that it is something that will be saved to database and will be retrieved from database - def __init__(self, name, price): + __tablename__ = "items" + + # Columns + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80)) + price = db.Column(db.Float(precision=2)) # precision: numbers after decimal point + + store_id = db.Column(db.Integer, db.ForeignKey("stores.id")) + store = db.relationship("StoreModel") + + def __init__(self, name, price, store_id): self.name = name self.price = price + self.store_id = store_id def json(self): - return {"name": self.name, "price": self.price} + return {"id": self.id,"store_id":self.store_id, "name": self.name, "price": self.price} # searches the database for items using name @classmethod def find_item_by_name(cls, name): - connection = sqlite3.connect('./test/data.db') - cursor = connection.cursor() - - query = "SELECT * FROM items WHERE name=?" - result = cursor.execute(query, (name,)) - - row = result.fetchone() - connection.close() - - if row: - # return cls(row[0], row[1]) - return cls(*row) # same as above - - # method to insert an item into - def insert(self): - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "INSERT INTO items VALUES (?, ?)" - cursor.execute(query, (self.name, self.price)) - - connection.commit() - connection.close() - - def update(self): - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "UPDATE items SET price=? WHERE name=?" - cursor.execute(query, (self.price, self.name)) - - connection.commit() - connection.close() - + # return cls.query.filter_by(name=name) # SELECT name FROM __tablename__ WHERE name=name + # this function would return a ItemModel object + return cls.query.filter_by(name=name).first() # SELECT name FROM __tablename__ WHERE name=name LIMIT 1 + + # method to insert or update an item into database + def save_to_database(self): + db.session.add(self) # session here is a collection of objects that wil be written to database + db.session.commit() + + def delete_from_database(self): + db.session.delete(self) + db.session.commit() diff --git a/models/store.py b/models/store.py new file mode 100644 index 0000000..97d8a04 --- /dev/null +++ b/models/store.py @@ -0,0 +1,33 @@ +from database import db + +class StoreModel(db.Model): # tells SQLAlchemy that it is something that will be saved to database and will be retrieved from database + + __tablename__ = "stores" + + # Columns + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80)) + + items = db.relationship("ItemModel", lazy="dynamic") # this will allow us to check which item is in store whose id is equal to it's id. + # lazy="dynamic" tells sqlalchemy to not create seperate objects for each item that is created + def __init__(self, name): + self.name = name + + def json(self): + return {"id": self.id, "name": self.name, "items": [item.json() for item in self.items.all()]} + + # searches the database for items using name + @classmethod + def find_item_by_name(cls, name): + # return cls.query.filter_by(name=name) # SELECT name FROM __tablename__ WHERE name=name + # this function would return a StoreModel object + return cls.query.filter_by(name=name).first() # SELECT name FROM __tablename__ WHERE name=name LIMIT 1 + + # method to insert or update an item into database + def save_to_database(self): + db.session.add(self) # session here is a collection of objects that wil be written to database + db.session.commit() + + def delete_from_database(self): + db.session.delete(self) + db.session.commit() diff --git a/models/user.py b/models/user.py index 18263db..f5bde4f 100644 --- a/models/user.py +++ b/models/user.py @@ -1,44 +1,27 @@ import sqlite3 +from database import db -class UserModel: +class UserModel(db.Model): - def __init__(self, _id, username, password): - self.id = _id + __tablename__ = "users" # will be used to tell sqlalchemy the table name for users + + # table columns for users table + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(80)) + password = db.Column(db.String(80)) + + def __init__(self, username, password): self.username = username self.password = password @classmethod def find_by_username(cls, username): - connection = sqlite3.connect('./test/data.db') - cursor = connection.cursor() - - query = "SELECT * FROM users WHERE username=?" - result = cursor.execute(query, (username,)) # parameters must be in the form of tuple. - - row = result.fetchone() - if row: - # user = cls(row[0], row[1], row[2]) - user = cls(*row) # is similar to passing all values of row - else: - user = None - - connection.close() - return user + return cls.query.filter_by(username=username).first() @classmethod def find_by_id(cls, _id): - connection = sqlite3.connect('./test/data.db') - cursor = connection.cursor() - - query = "SELECT * FROM users WHERE id=?" - result = cursor.execute(query, (_id,)) # parameters must be in the form of tuple. - - row = result.fetchone() - if row: - # user = cls(row[0], row[1], row[2]) - user = cls(*row) # is similar to passing all values of row - else: - user = None + return cls.query.filter_by(id=_id).first() - connection.close() - return user + def save_to_database(self): + db.session.add(self) + db.session.commit() \ No newline at end of file diff --git a/requiements.txt b/requirements.txt similarity index 93% rename from requiements.txt rename to requirements.txt index 16bcdb4..df44585 100644 --- a/requiements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Flask -Flask-RESTful -Flask-JWT +Flask +Flask-RESTful +Flask-JWT Flask-SQLAlchemy \ No newline at end of file diff --git a/resources/__pycache__/item.cpython-39.pyc b/resources/__pycache__/item.cpython-39.pyc index d96291831ed16e4a7059604a3d187fcc2208617f..779197585dc23ff0d4aff4633c79f1b376a0cf35 100644 GIT binary patch literal 2226 zcmZuy&2QX96rT^<>vg=%ri9W$smzyjea!>wo-} z{pJ($Cr-{k4oq&t&;p1cf)*sfFDq!t5?1nrQ=Id{Dc!^^y~ML~r|6V^;#=M=x@C|A zlzd8rCprg2bfo))CrdE*MHl8>I}ZijAaU>vZX#p`$Fai%~8HLw3$p4m^%e(AzhGG~|%Z=@H#$bEYoM*&#b38<0@J zaw_6B9IY)8(P+dII#Q9Z51ApeOH5_8poqs+=EuSAL(>Gob)Wu-LESl884 z@IcFAWSmxp8c&IO8TS19-klG(9;kXOhmGEPu-81StM$7Zo7p7aQpZ`*4IA5h@3V%? z>4@fJ&VHre(|tY*=lsw;B9weds>>9<0ADIx*y)X!N4|o1-5{Xj9RUVx#QfukNr;$> z#z(W|C@YlA#9k!7&2^)n{Q!ZRt$bWXQmI-+^>8=^oDTATK>qA^us815sH$b)6*_D@ z3vFcr`%N>oqfK9Dk7e4_smPjaJJVA2LG`JlF5NiY%H=;~cwd3R5@>F>4W2 zqim#@_1jrpz1y?_QddCf7+5w0$!e>cj#OQqdAkB?&%5Qdn(xDswtcKc3ibJH$zr8l zUvLTGg2TdP9hioUDHa0&0)SylgwMGkQ=$e9UxY}tI%k4j0T84vaLjTZK%#@Nfv=B6 z74tRKg_BheNZhqKRj;AoDiSQAHrc02>UET1Le(`S&!vw~rp-qn*Qh~gzyj{mi#(wC zJuVASS&J_iKehFkrY1&vf)|kvH-K1Oxnx6<(vTE0~@Yz<*aa zqiLZqU@fq^?E?IiEozb_K%p%30FEhJ>|>9!7rY2P#=qIZ_7>(*hd_MRr+pf-koE8V E4_`Xx!T^u|t;wv@J%vZc`C0(Pq&5E7J>)`3cGsFH}PD`Y%abQa)N91JI%rX<2AOKHX;mRXTSv2Uez=0r~BMy~1Gsh9bYZ`w{;%YrDN z3H+F49v^+bD8Yz>7fVZ>h+su;?i z&^`iXu>vWrfM6dd}sd!@)86kMb|Tx$Aqp|b$DS_UIXL^+9=u=eZ;i5%f< zx||A+Gj4JFN1GDi?-K5C_c__6QH^`te@>#njMjKyMrZg8ufu4aHz4>~ZR5waGmuG7 ztd7pFZX_z~CnDuxFV6F#4A(@smd5#$rlsw2dr)n~gs$xkkq&wcLOZ-HXyAPZZuKsh zlI+njozNXNX7bFK?Xd}2fwXXzP;T`Z#9%LJFB3||>tb{wfoMYfY`+-hyp{Y+A=#Gn zU@1M{PjcQxkM7!bH;*%+?M+qW7?~1jU)$9fdi+l0DR}3_t#+1|?JqkwIyXPa&r552s=3 z*yfRYm@u>X4QL#0US7lvkLfSKyWcF>xQ!bx*``V44lBu+jv05(kzKZ9jp}1-&zTTP z9+CVkg(t9*au?q7`phMd0l@17eB24}(Lh)`fKUL04u&3%PK0qPMa;KD@hnlL+W!fV zlr@NIG=Dn}g_MO1i(YRC9Bl3X4U_wSz+}@iSj$;xOWd<|4Q-_k%(ENIb*0@TS3;KZ z1ioR*Idq;!XPd`mEKgz|QLD^pGczbuc>!7qXA#NMEMT*Y(K>bMNj5SnXrb3JP#tha zU=66Kf+J8DOSWh618$)rb}Y_zYy@v?k7=Jy7$v|sfXO^Pe4&|i~M2da>g**e1jOs{(5Oga_!AEmd zugI^K73T6yaBBLm0M(w_N@1~^+Upg04g}OLBtR8Xd*Yes4NCz7MV2L{c6w<6)xwzq zH#m4HDRPP0(hk%ax&1oQZWYkS;89_12Q&cI+H{ur6n@rd219LCe*Z%Ih{E5)3MJX3 zs97K>kku&JDlJ1-YUm1hb221y8E9)C(st|F0d1i&Rdhe3ZGOf0nVd|~8_0j$57vTw zL3MDK3~6Npf*DT-Tb@Vr78F_af-z2b|vaTHL9scyFv26op}yD24n>V0DI3{$sBCL&Pv~9p-Gv=zOo5LM zx6To;_BlBBeq|F%$<}+IdBw&s8e_D|a_w_FK3WX2Q25_L~h8J#qp5mq?tE z78uuo1=5I&gyLL!9NawCl&wz diff --git a/resources/__pycache__/store.cpython-39.pyc b/resources/__pycache__/store.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e6d780a72b5d122e5720840fb5b8a36da60560c GIT binary patch literal 1521 zcmZux!EVz)5Zzrni3tg`P)fxCjHp0C$f`J^s4Aj}3q)0egs_S%*SkqwoH*TefLQ6N z{Q&rb=GaexBS&93^~3>AoS0cBX{vOi9nGv~cjmpBiC?Xj39P3-fBQcSLVlq!yG$@P zV5>R^PB@K7hq{!a&LY+^T!WHVgd5yECfpSC$Z$=t3%m$+QQHMxYLc3D1}~5r&8%&q z;=T+7=;dY-OYtV=A`0;H>|$VSz*egu1aT=RF5{H5W8xZlK-bIzx#JL7LBAK^)yV=> z1osQr>JEs6oX{a1(L*+5a(T#3*oZU%59CN2HAA9vw%7{0+zS)Y@pcDZ*YAkT+*fh; z)W}RFqE=?=vx36>Pl>z=m;OE3e73VC<9!h%YG-SZ?8V*fm(90+FWix1%xXv9aC(Ex zXp5wXNueOLOih|z(fK>@Wex*+X$)JSOfbl0BqXHVXt5@o4(So#N-H@kO5Ty~3MKdh zKNI{4EmkD&0qYt8A7cbH!ke{HBP(@;Qhr;cOF9YLkEG8Bw)hgNL^ct|dyxQXJNJ*^>y z62}*}?lFs51?###3*hX+nhx6%9M2CM(v#)Q`5M|GfYMGE>KH>e=L#suEH{pU_kD`P zwMmZXnBlCb$y65}z}Wae6Sl(mZ89VuDu*zoCuBsvu>-T2!>duh3g>$9< zV^~_f@OA@w9TCV|D3(#^DqU8a+wk=PZ2gi&CE8f}YAf>9M-Tonl2$*G7{{$Z3y4TL fn!S9QkTHE{hJtC~Gpn9A%{o>`SHA+&vvBV}Km$I_ literal 0 HcmV?d00001 diff --git a/resources/__pycache__/user.cpython-39.pyc b/resources/__pycache__/user.cpython-39.pyc index d3874b63e234027f8cd01369e05f477aa27e3b86..571f4578475bf5683c246d2d28ca0455e8bac7c4 100644 GIT binary patch delta 309 zcmZqRyv)v*$ji&c00bMJyi0Us*~sV4$j1!ivH-C&5Er{mPG;0lW=>$_n4;9;{L-T2)Z!SB2EBsHTPy|n#U&CTxA6c821YI>J|-R}K1L3vD#1{onxNG5 z%;L$F%rT;3KxwcANQCI*SIj1yx7dpdb23X(jVCL!80vuBfUE?_y~SaZo1apelWNBZ PrjJQqW delta 468 zcmYjO!Aiq07*4Ww?Wz_Lg-t#5A~=-QsUV7MPN^b}DQ6HuM3!^#!)0 z7s0Eq;VsV~K7c1v@nHD>@8`>x@cn=CVLat*e`?ACYOOzi`9uB9K7zKcXjbKcN**Nv zTt3l9S*(xY5Dn1C7=vL3XNTG#GcpI-0Ag4G3XKA2qcMU&oym>CZ?)2jO`HoMw%Vu( ziWA8z+}nAuORgYXxY!qd312-d9XFcZdCNI&v`(Fv6ULp(TK&RnI?IiVdVSTYswgrG zB%g2vP9%9$el+-PClq8u8Uc+W5(t?MV#X zYqtDe=rY1-%mTvQwEa@AFSQ=!BA-6utO5WnWTQ#VLMGBs9+}BIx|v&4!mr&wSV*=r kn>w3TQgW9mucqDnmlc)fZkOV?Ln=@)p8l2zr{N^}0RuI7>i_@% diff --git a/resources/item.py b/resources/item.py index e70727a..1ecaecf 100644 --- a/resources/item.py +++ b/resources/item.py @@ -14,6 +14,11 @@ class Item(Resource): required=True, help="This field cannot be blank" ) + parser.add_argument("store_id", + type=int, + required=True, + help="Every item needs a store id." + ) # TO GET ITEM WITH NAME @jwt_required() @@ -32,10 +37,10 @@ def post(self, name): data = Item.parser.parse_args() # data = request.get_json() # get_json(force=True) means, we don't need a content type header - item = ItemModel(name, data["price"]) + item = ItemModel(name, **data) try: - item.insert() + item.save_to_database() except: return {"messege": "An error occured."}, 500 @@ -44,17 +49,9 @@ def post(self, name): # TO DELETE AN ITEM @jwt_required() def delete(self, name): - # check if there exists any item by name: "name" - # if exists then delete it - if ItemModel.find_item_by_name(name): - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "DELETE FROM items WHERE name=?" - cursor.execute(query, (name,)) - - connection.commit() - connection.close() + item = ItemModel.find_item_by_name(name) + if item: + item.delete_from_database() return {"messege": "Item deleted"} # if doesn't exist, skip deleting @@ -66,34 +63,22 @@ def put(self, name): # data = request.get_json() item = ItemModel.find_item_by_name(name) - updated_item = ItemModel(name, data["price"]) # if item is not available, add it if item is None: - try: - updated_item.insert() - except: - return {"message": "An error occured while inserting."}, 500 + item = ItemModel(name, **data) # if item exists, update it else: - try: - updated_item.update() - except: - return {"message": "An error occured while updating."}, 500 - - return updated_item.json() + item.price = data['price'] + item.store_id = data['store_id'] + + # whether item is changed or inserted, it has to be saved to db + item.save_to_database() + return item.json() class ItemList(Resource): # TO GET ALL ITEMS def get(self): - items = [] - connection = sqlite3.connect("./test/data.db") - cursor = connection.cursor() - - query = "SELECT * FROM items" - for row in cursor.execute(query): - items.append({"name": row[0], "price": row[1]}) - - connection.close() - return {"items": items} \ No newline at end of file + # return {"item": list(map(lambda x: x.json(), ItemModel.query.all()))} + return {"items": [item.json() for item in ItemModel.query.all()]} \ No newline at end of file diff --git a/resources/store.py b/resources/store.py new file mode 100644 index 0000000..9dad423 --- /dev/null +++ b/resources/store.py @@ -0,0 +1,38 @@ +from flask_restful import Resource +from models.store import StoreModel + +class Store(Resource): + + def get(self, name): + store = StoreModel.find_item_by_name(name) + if store: + return store.json() + + def post(self, name): + if StoreModel.find_item_by_name(name): + return {"message": "Store alrady exists."}, 400 + + store = StoreModel(name) + + try: + store.save_to_database() + except: + return {"message": "An error occured while creating the store."}, 500 + + return store.json(), 201 + + + + def delete(self, name): + store = StoreModel.find_item_by_name(name) + if store: + store.delete_from_database() + return {"message": "store deleetd."} + + return {"message": "store don't exist"} + + +class StoreList(Resource): + def get(self): + # return {"item": list(map(lambda x: x.json(), ItemModel.query.all()))} + return {"stores": [store.json() for store in StoreModel.query.all()]} \ No newline at end of file diff --git a/resources/user.py b/resources/user.py index 379de51..3f6eed1 100644 --- a/resources/user.py +++ b/resources/user.py @@ -28,17 +28,7 @@ def post(self): # if exists, then don't add return {"message": "An user with that username already exists."}, 400 - # else...continue - # 1. Connect to database - connection = sqlite3.connect('./test/data.db') - # 2. Create database cursor - cursor = connection.cursor() - # 3. SQL query to inser new useer information - query = "INSERT INTO users VALUES (NULL, ?, ?)" - - cursor.execute(query, (data["username"], data["password"])) - # 4. Commit the changes and close the connection to database - connection.commit() - connection.close() + user = UserModel(**data) # since parser only takes in username and password, only those two will be added. + user.save_to_database() return {"messege": "User added successfully."}, 201 \ No newline at end of file diff --git a/test/test.py b/test/test.py deleted file mode 100644 index 56eab91..0000000 --- a/test/test.py +++ /dev/null @@ -1,34 +0,0 @@ -import sqlite3 - -connection = sqlite3.connect('./test/test.db') - -cursor = connection.cursor() - -create_table = "CREATE TABLE IF NOT EXISTS users (id int PRIMARY KEY, username text, password text)" -cursor.execute(create_table) - -# user1 = (1, "bob", "1234") - -# insert_query = "INSERT INTO users VALUES (?, ?, ?)" - -# cursor.execute(insert_query, user1) - -users = [ - (2, "rolf", "2345"), - (3, "smith", "3456"), - (4, "john", "4567"), - (5, "clint", "5678") -] - -# cursor.executemany(insert_query, users) - -select_query = "SELECT username, password FROM users where username='gold'" -for row in cursor.execute(select_query): - print(row) - - - -# commiting the changes to database -connection.commit() -# closing the connection to database -connection.close() \ No newline at end of file