From ad748fe12c34f93b178635b84bf41825e86c713f Mon Sep 17 00:00:00 2001 From: petak5 Date: Fri, 3 Apr 2020 21:21:18 +0200 Subject: [PATCH 01/14] Added Flask Marshmallow to the project, implemented get_all_users endpoint. --- Pipfile | 1 + Pipfile.lock | 92 +++++++++++++++------------ src/api/__init__.py | 2 + src/api/controllers/userController.py | 4 ++ src/api/models/userModel.py | 5 ++ src/api/views/__init__.py | 2 +- src/api/views/userView.py | 17 +++-- 7 files changed, 79 insertions(+), 44 deletions(-) diff --git a/Pipfile b/Pipfile index e23da5a..9f646fd 100644 --- a/Pipfile +++ b/Pipfile @@ -12,6 +12,7 @@ pyopenssl = "*" flask-sqlalchemy = "*" flask = "*" sqlalchemy-utils = "*" +flask-marshmallow = "*" [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index 8597f10..bdfe873 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "8b7b9c6cbf59aa0bd844fa557bc1baa8ed0644b7b52c686463a46a250b389fbc" + "sha256": "b146ba7a590efe52e37f89dcb65ca5f9700c8e5e455b1bd06ece4e498e4d6cc5" }, "pipfile-spec": 6, "requires": { @@ -51,44 +51,50 @@ }, "click": { "hashes": [ - "sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13", - "sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7" + "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", + "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" ], - "version": "==7.0" + "version": "==7.1.1" }, "cryptography": { "hashes": [ - "sha256:02079a6addc7b5140ba0825f542c0869ff4df9a69c360e339ecead5baefa843c", - "sha256:1df22371fbf2004c6f64e927668734070a8953362cd8370ddd336774d6743595", - "sha256:369d2346db5934345787451504853ad9d342d7f721ae82d098083e1f49a582ad", - "sha256:3cda1f0ed8747339bbdf71b9f38ca74c7b592f24f65cdb3ab3765e4b02871651", - "sha256:44ff04138935882fef7c686878e1c8fd80a723161ad6a98da31e14b7553170c2", - "sha256:4b1030728872c59687badcca1e225a9103440e467c17d6d1730ab3d2d64bfeff", - "sha256:58363dbd966afb4f89b3b11dfb8ff200058fbc3b947507675c19ceb46104b48d", - "sha256:6ec280fb24d27e3d97aa731e16207d58bd8ae94ef6eab97249a2afe4ba643d42", - "sha256:7270a6c29199adc1297776937a05b59720e8a782531f1f122f2eb8467f9aab4d", - "sha256:73fd30c57fa2d0a1d7a49c561c40c2f79c7d6c374cc7750e9ac7c99176f6428e", - "sha256:7f09806ed4fbea8f51585231ba742b58cbcfbfe823ea197d8c89a5e433c7e912", - "sha256:90df0cc93e1f8d2fba8365fb59a858f51a11a394d64dbf3ef844f783844cc793", - "sha256:971221ed40f058f5662a604bd1ae6e4521d84e6cad0b7b170564cc34169c8f13", - "sha256:a518c153a2b5ed6b8cc03f7ae79d5ffad7315ad4569b2d5333a13c38d64bd8d7", - "sha256:b0de590a8b0979649ebeef8bb9f54394d3a41f66c5584fff4220901739b6b2f0", - "sha256:b43f53f29816ba1db8525f006fa6f49292e9b029554b3eb56a189a70f2a40879", - "sha256:d31402aad60ed889c7e57934a03477b572a03af7794fa8fb1780f21ea8f6551f", - "sha256:de96157ec73458a7f14e3d26f17f8128c959084931e8997b9e655a39c8fde9f9", - "sha256:df6b4dca2e11865e6cfbfb708e800efb18370f5a46fd601d3755bc7f85b3a8a2", - "sha256:ecadccc7ba52193963c0475ac9f6fa28ac01e01349a2ca48509667ef41ffd2cf", - "sha256:fb81c17e0ebe3358486cd8cc3ad78adbae58af12fc2bf2bc0bb84e8090fa5ce8" - ], - "version": "==2.8" + "sha256:0cacd3ef5c604b8e5f59bf2582c076c98a37fe206b31430d0cd08138aff0986e", + "sha256:192ca04a36852a994ef21df13cca4d822adbbdc9d5009c0f96f1d2929e375d4f", + "sha256:19ae795137682a9778892fb4390c07811828b173741bce91e30f899424b3934d", + "sha256:1b9b535d6b55936a79dbe4990b64bb16048f48747c76c29713fea8c50eca2acf", + "sha256:2a2ad24d43398d89f92209289f15265107928f22a8d10385f70def7a698d6a02", + "sha256:3be7a5722d5bfe69894d3f7bbed15547b17619f3a88a318aab2e37f457524164", + "sha256:49870684da168b90110bbaf86140d4681032c5e6a2461adc7afdd93be5634216", + "sha256:587f98ce27ac4547177a0c6fe0986b8736058daffe9160dcf5f1bd411b7fbaa1", + "sha256:5aca6f00b2f42546b9bdf11a69f248d1881212ce5b9e2618b04935b87f6f82a1", + "sha256:6b744039b55988519cc183149cceb573189b3e46e16ccf6f8c46798bb767c9dc", + "sha256:6b91cab3841b4c7cb70e4db1697c69f036c8bc0a253edc0baa6783154f1301e4", + "sha256:7598974f6879a338c785c513e7c5a4329fbc58b9f6b9a6305035fca5b1076552", + "sha256:7a279f33a081d436e90e91d1a7c338553c04e464de1c9302311a5e7e4b746088", + "sha256:95e1296e0157361fe2f5f0ed307fd31f94b0ca13372e3673fa95095a627636a1", + "sha256:9fc9da390e98cb6975eadf251b6e5fa088820141061bf041cd5c72deba1dc526", + "sha256:cc20316e3f5a6b582fc3b029d8dc03aabeb645acfcb7fc1d9848841a33265748", + "sha256:d1bf5a1a0d60c7f9a78e448adcb99aa101f3f9588b16708044638881be15d6bc", + "sha256:ed1d0760c7e46436ec90834d6f10477ff09475c692ed1695329d324b2c5cd547", + "sha256:ef9a55013676907df6c9d7dd943eb1770d014f68beaa7e73250fb43c759f4585" + ], + "version": "==2.9" }, "flask": { "hashes": [ - "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", - "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6" + "sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060", + "sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557" ], "index": "pypi", - "version": "==1.1.1" + "version": "==1.1.2" + }, + "flask-marshmallow": { + "hashes": [ + "sha256:01520ef1851ccb64d4ffb33196cddff895cc1302ae1585bff1abf58684a8111a", + "sha256:28b969193958d9602ab5d6add6d280e0e360c8e373d3492c2f73b024ecd36374" + ], + "index": "pypi", + "version": "==0.11.0" }, "flask-mysql": { "hashes": [ @@ -165,11 +171,19 @@ ], "version": "==1.1.1" }, + "marshmallow": { + "hashes": [ + "sha256:90854221bbb1498d003a0c3cc9d8390259137551917961c8b5258c64026b2f85", + "sha256:ac2e13b30165501b7d41fc0371b8df35944f5849769d136f20e2c5f6cdc6e665" + ], + "version": "==3.5.1" + }, "pycparser": { "hashes": [ - "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3" + "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", + "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" ], - "version": "==2.19" + "version": "==2.20" }, "pymysql": { "hashes": [ @@ -195,23 +209,23 @@ }, "sqlalchemy": { "hashes": [ - "sha256:64a7b71846db6423807e96820993fa12a03b89127d278290ca25c0b11ed7b4fb" + "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445" ], - "version": "==1.3.13" + "version": "==1.3.15" }, "sqlalchemy-utils": { "hashes": [ - "sha256:4e637c88bf3ac5f99b7d72342092a1f636bea1287b2e3e17d441b0413771f86e" + "sha256:f268af5bc03597fe7690d60df3e5f1193254a83e07e4686f720f61587ec4493a" ], "index": "pypi", - "version": "==0.36.1" + "version": "==0.36.3" }, "werkzeug": { "hashes": [ - "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096", - "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16" + "sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43", + "sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c" ], - "version": "==1.0.0" + "version": "==1.0.1" } }, "develop": {} diff --git a/src/api/__init__.py b/src/api/__init__.py index 6c88e10..39c05cb 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -3,7 +3,9 @@ """ from flask import Flask +from flask_marshmallow import Marshmallow app = Flask(__name__) +ma = Marshmallow(app) from api.models import db import api.models diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index a7806d2..7daec95 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -10,5 +10,9 @@ def create_user(self, **kwargs): def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() return user + + def get_all_users(self, **kwargs): + all_users = User.query.all() + return all_users userController = UserController() diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 389d5e6..4629d45 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -1,3 +1,4 @@ +from api import ma from api.models import db class UserHasProject(db.Model): @@ -20,6 +21,10 @@ class User(db.Model): def __repr__(self): return '' % self.name + +class UserSchema(ma.Schema): + class Meta: + fields = ('id', 'name') class UserLink(db.Model): id = db.Column(db.Integer, primary_key=True) diff --git a/src/api/views/__init__.py b/src/api/views/__init__.py index a414909..960823d 100644 --- a/src/api/views/__init__.py +++ b/src/api/views/__init__.py @@ -1,4 +1,4 @@ """ The views package """ -import api.views.userView +from api.views import userView diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 4107d5b..54fa58e 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,7 +1,10 @@ +from flask import request, jsonify from api import app - from api.controllers import userController -from flask import request +from api.models.userModel import UserSchema + +userSchema = UserSchema() +usersSchema = UserSchema(many=True) @app.route("/user/push", methods=['POST']) def push_user(): @@ -10,5 +13,11 @@ def push_user(): @app.route("/user/get/", methods=['GET']) def get_user(name): - user = userController.get_user(username=name) - return user.username + user = userController.get_user(name=name) + return user.name + +@app.route("/users", methods=['GET']) +def get_all_users(): + all_users = userController.get_all_users() + + return jsonify(usersSchema.dump(all_users)) \ No newline at end of file From 5e6598f533ac2e65b39dd6b54cc5df27ac0e4d2c Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 5 Apr 2020 13:27:04 +0200 Subject: [PATCH 02/14] Fixed User's get and post routes and added a delete route. --- src/api/controllers/userController.py | 11 ++++++++- src/api/views/userView.py | 32 +++++++++++++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index 7daec95..7ff89a8 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -7,12 +7,21 @@ def create_user(self, **kwargs): self.session.add(user) self.session.commit() + return user + def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() + return user - + def get_all_users(self, **kwargs): all_users = User.query.all() + return all_users + def delete_user(self, id): + result = User.query.filter_by(id=id).delete() + db.session.commit() + return result + userController = UserController() diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 54fa58e..1cdb491 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -6,18 +6,32 @@ userSchema = UserSchema() usersSchema = UserSchema(many=True) -@app.route("/user/push", methods=['POST']) -def push_user(): - user = userController.create_user(**request.form) - return "200OK" +@app.route("/users", methods=['POST']) +def post_user(): + user = userController.create_user(**request.get_json()) -@app.route("/user/get/", methods=['GET']) -def get_user(name): - user = userController.get_user(name=name) - return user.name + return jsonify(userSchema.dump(user)), 201 + +@app.route("/users/", methods=['GET']) +def get_user(id): + user = userController.get_user(id=id) + + if user: + return jsonify(userSchema.dump(user)), 200 + else: + return "", 404 @app.route("/users", methods=['GET']) def get_all_users(): all_users = userController.get_all_users() - return jsonify(usersSchema.dump(all_users)) \ No newline at end of file + return jsonify(usersSchema.dump(all_users)), 200 + +@app.route("/users/", methods=['DELETE']) +def delete_user(id): + result = userController.delete_user(id) + + if result: + return "", 202 + else: + return "", 404 \ No newline at end of file From 60ba89b6e21c7a80268b4cb712e8e6c193a09490 Mon Sep 17 00:00:00 2001 From: petak5 Date: Sat, 11 Apr 2020 20:37:14 +0200 Subject: [PATCH 03/14] Removed Flask Marshmallow and replaced it with manual iterating over model properties. Fixed users delete route. --- Pipfile | 1 - Pipfile.lock | 41 ++++++++++++++------------- src/api/__init__.py | 4 +-- src/api/controllers/userController.py | 20 +++++++++++-- src/api/models/projectModel.py | 23 +++++++++++++++ src/api/models/userModel.py | 36 +++++++++++++++++++---- src/api/views/userView.py | 16 +++++------ 7 files changed, 102 insertions(+), 39 deletions(-) diff --git a/Pipfile b/Pipfile index 9f646fd..e23da5a 100644 --- a/Pipfile +++ b/Pipfile @@ -12,7 +12,6 @@ pyopenssl = "*" flask-sqlalchemy = "*" flask = "*" sqlalchemy-utils = "*" -flask-marshmallow = "*" [requires] python_version = "3.7" diff --git a/Pipfile.lock b/Pipfile.lock index bdfe873..bc2d895 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b146ba7a590efe52e37f89dcb65ca5f9700c8e5e455b1bd06ece4e498e4d6cc5" + "sha256": "8b7b9c6cbf59aa0bd844fa557bc1baa8ed0644b7b52c686463a46a250b389fbc" }, "pipfile-spec": 6, "requires": { @@ -88,14 +88,6 @@ "index": "pypi", "version": "==1.1.2" }, - "flask-marshmallow": { - "hashes": [ - "sha256:01520ef1851ccb64d4ffb33196cddff895cc1302ae1585bff1abf58684a8111a", - "sha256:28b969193958d9602ab5d6add6d280e0e360c8e373d3492c2f73b024ecd36374" - ], - "index": "pypi", - "version": "==0.11.0" - }, "flask-mysql": { "hashes": [ "sha256:7946e6367eaf1d87df3ae6b06af07b33fcd7cc8c04a9d0be2d208f23311d25e5", @@ -171,13 +163,6 @@ ], "version": "==1.1.1" }, - "marshmallow": { - "hashes": [ - "sha256:90854221bbb1498d003a0c3cc9d8390259137551917961c8b5258c64026b2f85", - "sha256:ac2e13b30165501b7d41fc0371b8df35944f5849769d136f20e2c5f6cdc6e665" - ], - "version": "==3.5.1" - }, "pycparser": { "hashes": [ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", @@ -209,9 +194,27 @@ }, "sqlalchemy": { "hashes": [ - "sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445" - ], - "version": "==1.3.15" + "sha256:083e383a1dca8384d0ea6378bd182d83c600ed4ff4ec8247d3b2442cf70db1ad", + "sha256:0a690a6486658d03cc6a73536d46e796b6570ac1f8a7ec133f9e28c448b69828", + "sha256:114b6ace30001f056e944cebd46daef38fdb41ebb98f5e5940241a03ed6cad43", + "sha256:128f6179325f7597a46403dde0bf148478f868df44841348dfc8d158e00db1f9", + "sha256:13d48cd8b925b6893a4e59b2dfb3e59a5204fd8c98289aad353af78bd214db49", + "sha256:211a1ce7e825f7142121144bac76f53ac28b12172716a710f4bf3eab477e730b", + "sha256:2dc57ee80b76813759cccd1a7affedf9c4dbe5b065a91fb6092c9d8151d66078", + "sha256:3e625e283eecc15aee5b1ef77203bfb542563fa4a9aa622c7643c7b55438ff49", + "sha256:43078c7ec0457387c79b8d52fff90a7ad352ca4c7aa841c366238c3e2cf52fdf", + "sha256:5b1bf3c2c2dca738235ce08079783ef04f1a7fc5b21cf24adaae77f2da4e73c3", + "sha256:6056b671aeda3fc451382e52ab8a753c0d5f66ef2a5ccc8fa5ba7abd20988b4d", + "sha256:68d78cf4a9dfade2e6cf57c4be19f7b82ed66e67dacf93b32bb390c9bed12749", + "sha256:7025c639ce7e170db845e94006cf5f404e243e6fc00d6c86fa19e8ad8d411880", + "sha256:7224e126c00b8178dfd227bc337ba5e754b197a3867d33b9f30dc0208f773d70", + "sha256:7d98e0785c4cd7ae30b4a451416db71f5724a1839025544b4edbd92e00b91f0f", + "sha256:8d8c21e9d4efef01351bf28513648ceb988031be4159745a7ad1b3e28c8ff68a", + "sha256:bbb545da054e6297242a1bb1ba88e7a8ffb679f518258d66798ec712b82e4e07", + "sha256:d00b393f05dbd4ecd65c989b7f5a81110eae4baea7a6a4cdd94c20a908d1456e", + "sha256:e18752cecaef61031252ca72031d4d6247b3212ebb84748fc5d1a0d2029c23ea" + ], + "version": "==1.3.16" }, "sqlalchemy-utils": { "hashes": [ diff --git a/src/api/__init__.py b/src/api/__init__.py index 39c05cb..312906b 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -3,9 +3,9 @@ """ from flask import Flask -from flask_marshmallow import Marshmallow app = Flask(__name__) -ma = Marshmallow(app) +# Disable sorting of the jsonified data +app.config['JSON_SORT_KEYS'] = False from api.models import db import api.models diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index 7ff89a8..d2ff85d 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -1,4 +1,4 @@ -from api.models import db, User +from api.models import db, User, UserHasProject, UserLink class UserController: session = db.session() @@ -20,8 +20,22 @@ def get_all_users(self, **kwargs): return all_users def delete_user(self, id): - result = User.query.filter_by(id=id).delete() + # Remove all user's links + for link in UserLink.query.filter_by(user_id=id).all(): + db.session.delete(link) + + # Remove user from all projects + for project in UserHasProject.query.filter_by(user_id=id).all(): + db.session.delete(project) + + user = User.query.filter_by(id=id).first() + + if user == None: + return user + + db.session.delete(user) db.session.commit() - return result + + return user userController = UserController() diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index 04be1fa..ec0d717 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -11,6 +11,19 @@ class Project(db.Model): users = db.relationship('UserHasProject', back_populates='project') links = db.relationship('ProjectLink', backref='project', lazy=True) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'description': self.description, + 'languages': self.languages, + 'development_status': self.development_status, + 'creation_date': self.creation_date, + 'release_date': self.release_date, + 'links': [ link.as_dict() for link in self.links ] + } + return obj_d + def __repr__(self): return '' % self.name @@ -20,5 +33,15 @@ class ProjectLink(db.Model): url = db.Column(db.Text, nullable=False) project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) + # todo: decide if this should contain project_id (it is already present in the model) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'project_id': self.project_id + } + return obj_d + def __repr__(self): return '' % self.name \ No newline at end of file diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 4629d45..8601226 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -1,4 +1,3 @@ -from api import ma from api.models import db class UserHasProject(db.Model): @@ -8,6 +7,14 @@ class UserHasProject(db.Model): project = db.relationship('Project', back_populates='users') role = db.Column(db.Integer, nullable=False) + # todo: figure out where to put the role property + + def user_as_dict(self): + return self.user.as_dict() + + def project_as_dict(self): + return self.project.as_dict() + class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) @@ -19,12 +26,22 @@ class User(db.Model): projects = db.relationship('UserHasProject', back_populates='user') links = db.relationship('UserLink', backref='user', lazy=True) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'bio': self.bio, + 'languages': self.languages, + 'interests': self.interests, + 'location': self.location, + 'occupation': self.occupation, + 'projects': [ project.project_as_dict() for project in self.projects ], + 'links': [ link.as_dict() for link in self.links ] + } + return obj_d + def __repr__(self): return '' % self.name - -class UserSchema(ma.Schema): - class Meta: - fields = ('id', 'name') class UserLink(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -32,5 +49,14 @@ class UserLink(db.Model): url = db.Column(db.Text, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'user_id': self.user_id + } + return obj_d + def __repr__(self): return '' % self.name \ No newline at end of file diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 1cdb491..60e51cb 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,23 +1,19 @@ from flask import request, jsonify from api import app from api.controllers import userController -from api.models.userModel import UserSchema - -userSchema = UserSchema() -usersSchema = UserSchema(many=True) @app.route("/users", methods=['POST']) def post_user(): user = userController.create_user(**request.get_json()) - return jsonify(userSchema.dump(user)), 201 + return jsonify(user.as_dict()), 201 @app.route("/users/", methods=['GET']) def get_user(id): user = userController.get_user(id=id) if user: - return jsonify(userSchema.dump(user)), 200 + return jsonify(user.as_dict()), 200 else: return "", 404 @@ -25,13 +21,15 @@ def get_user(id): def get_all_users(): all_users = userController.get_all_users() - return jsonify(usersSchema.dump(all_users)), 200 + users = [ user.as_dict() for user in all_users ] + + return jsonify(users), 200 @app.route("/users/", methods=['DELETE']) def delete_user(id): - result = userController.delete_user(id) + user = userController.delete_user(id) - if result: + if user: return "", 202 else: return "", 404 \ No newline at end of file From 400809f864af9737d2c8111bff1744c79636ddfe Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 12 Apr 2020 09:52:54 +0200 Subject: [PATCH 04/14] Implemented Project routes. --- src/api/controllers/projectController.py | 31 +++++++++++++++++++-- src/api/models/projectModel.py | 6 ++-- src/api/models/userModel.py | 4 +-- src/api/views/__init__.py | 2 +- src/api/views/projectView.py | 35 ++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 src/api/views/projectView.py diff --git a/src/api/controllers/projectController.py b/src/api/controllers/projectController.py index 6d4982e..bfdaebe 100644 --- a/src/api/controllers/projectController.py +++ b/src/api/controllers/projectController.py @@ -1,4 +1,4 @@ -from api.models import db, Project +from api.models import db, Project, UserHasProject, ProjectLink class ProjectController: session = db.session() @@ -7,8 +7,35 @@ def create_project(self, **kwargs): self.session.add(project) self.session.commit() + return project + def get_project(self, **kwargs): project = Project.query.filter_by(**kwargs).first() + + return project + + def get_all_projects(self, **kwargs): + all_projects = Project.query.all() + + return all_projects + + def delete_project(self, id): + # Remove all project's links + for link in ProjectLink.query.filter_by(project_id=id).all(): + db.session.delete(link) + + # Remove project from all users + for project in UserHasProject.query.filter_by(project_id=id).all(): + db.session.delete(project) + + project = Project.query.filter_by(id=id).first() + + if project == None: + return project + + db.session.delete(project) + db.session.commit() + return project -projectController = ProjectController() +projectController = ProjectController() \ No newline at end of file diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index ec0d717..4625394 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -1,12 +1,13 @@ from api.models import db +from datetime import datetime class Project(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) description = db.Column(db.Text, nullable=False) languages = db.Column(db.Text) - development_status = db.Column(db.Integer, nullable=False) - creation_date = db.Column(db.DateTime, nullable=False) + development_status = db.Column(db.Integer, nullable=False, default=0) + creation_date = db.Column(db.DateTime, nullable=False, default=datetime.now()) release_date = db.Column(db.DateTime) users = db.relationship('UserHasProject', back_populates='project') links = db.relationship('ProjectLink', backref='project', lazy=True) @@ -20,6 +21,7 @@ def as_dict(self): 'development_status': self.development_status, 'creation_date': self.creation_date, 'release_date': self.release_date, + 'users': [ user.user_as_dict() for user in self.users ], 'links': [ link.as_dict() for link in self.links ] } return obj_d diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 8601226..d18ca83 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -10,10 +10,10 @@ class UserHasProject(db.Model): # todo: figure out where to put the role property def user_as_dict(self): - return self.user.as_dict() + return { 'user_id': self.user_id, 'role': self.role } def project_as_dict(self): - return self.project.as_dict() + return { 'project_id': self.project_id, 'role': self.role } class User(db.Model): id = db.Column(db.Integer, primary_key=True) diff --git a/src/api/views/__init__.py b/src/api/views/__init__.py index 960823d..b918b65 100644 --- a/src/api/views/__init__.py +++ b/src/api/views/__init__.py @@ -1,4 +1,4 @@ """ The views package """ -from api.views import userView +from api.views import userView, projectView diff --git a/src/api/views/projectView.py b/src/api/views/projectView.py new file mode 100644 index 0000000..584a1fa --- /dev/null +++ b/src/api/views/projectView.py @@ -0,0 +1,35 @@ +from flask import request, jsonify +from api import app +from api.controllers import projectController + +@app.route("/projects", methods=['POST']) +def post_project(): + project = projectController.create_project(**request.get_json()) + + return jsonify(project.as_dict()), 201 + +@app.route("/projects/", methods=['GET']) +def get_project(id): + project = projectController.get_project(id=id) + + if project: + return jsonify(project.as_dict()), 200 + else: + return "", 404 + +@app.route("/projects", methods=['GET']) +def get_all_projects(): + all_projects = projectController.get_all_projects() + + projects = [ project.as_dict() for project in all_projects ] + + return jsonify(projects), 200 + +@app.route("/projects/", methods=['DELETE']) +def delete_project(id): + project = projectController.delete_project(id) + + if project: + return "", 202 + else: + return "", 404 \ No newline at end of file From a83e04cf7cf4da5b776cab612646ff3189fada47 Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 12 Apr 2020 10:12:09 +0200 Subject: [PATCH 05/14] Moved models to separate files. --- src/api/models/__init__.py | 9 +++++-- src/api/models/projectLinkModel.py | 20 ++++++++++++++++ src/api/models/projectModel.py | 22 +++-------------- src/api/models/userHasProjectModel.py | 14 +++++++++++ src/api/models/userLinkModel.py | 19 +++++++++++++++ src/api/models/userModel.py | 34 ++------------------------- 6 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 src/api/models/projectLinkModel.py create mode 100644 src/api/models/userHasProjectModel.py create mode 100644 src/api/models/userLinkModel.py diff --git a/src/api/models/__init__.py b/src/api/models/__init__.py index 13a7a3c..e160639 100644 --- a/src/api/models/__init__.py +++ b/src/api/models/__init__.py @@ -3,9 +3,14 @@ """ from sys import argv from datetime import datetime + from api.models.database import db, init_db -from api.models.userModel import UserHasProject, User, UserLink -from api.models.projectModel import Project, ProjectLink + +from api.models.userModel import User +from api.models.userLinkModel import UserLink +from api.models.projectModel import Project +from api.models.projectLinkModel import ProjectLink +from api.models.userHasProjectModel import UserHasProject if '--reset-db' in argv: init_db(True) diff --git a/src/api/models/projectLinkModel.py b/src/api/models/projectLinkModel.py new file mode 100644 index 0000000..929d528 --- /dev/null +++ b/src/api/models/projectLinkModel.py @@ -0,0 +1,20 @@ +from api.models import db + +class ProjectLink(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + url = db.Column(db.Text, nullable=False) + project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) + + # todo: decide if this should contain project_id (it is already present in the model) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'project_id': self.project_id + } + return obj_d + + def __repr__(self): + return '' % self.name diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index 4625394..b5cfa15 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -1,6 +1,9 @@ from api.models import db from datetime import datetime +from api.models.userHasProjectModel import UserHasProject +from api.models.projectLinkModel import ProjectLink + class Project(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) @@ -28,22 +31,3 @@ def as_dict(self): def __repr__(self): return '' % self.name - -class ProjectLink(db.Model): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80), nullable=False) - url = db.Column(db.Text, nullable=False) - project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) - - # todo: decide if this should contain project_id (it is already present in the model) - def as_dict(self): - obj_d = { - 'id': self.id, - 'name': self.name, - 'url': self.url, - 'project_id': self.project_id - } - return obj_d - - def __repr__(self): - return '' % self.name \ No newline at end of file diff --git a/src/api/models/userHasProjectModel.py b/src/api/models/userHasProjectModel.py new file mode 100644 index 0000000..5bc446e --- /dev/null +++ b/src/api/models/userHasProjectModel.py @@ -0,0 +1,14 @@ +from api.models import db + +class UserHasProject(db.Model): + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) + project_id = db.Column(db.Integer, db.ForeignKey('project.id'), primary_key=True) + user = db.relationship('User', back_populates='projects') + project = db.relationship('Project', back_populates='users') + role = db.Column(db.Integer, nullable=False) + + def user_as_dict(self): + return { 'user_id': self.user_id, 'role': self.role } + + def project_as_dict(self): + return { 'project_id': self.project_id, 'role': self.role } diff --git a/src/api/models/userLinkModel.py b/src/api/models/userLinkModel.py new file mode 100644 index 0000000..64fa5fa --- /dev/null +++ b/src/api/models/userLinkModel.py @@ -0,0 +1,19 @@ +from api.models import db + +class UserLink(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + url = db.Column(db.Text, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'user_id': self.user_id + } + return obj_d + + def __repr__(self): + return '' % self.name diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index d18ca83..8214414 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -1,19 +1,7 @@ from api.models import db -class UserHasProject(db.Model): - user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) - project_id = db.Column(db.Integer, db.ForeignKey('project.id'), primary_key=True) - user = db.relationship('User', back_populates='projects') - project = db.relationship('Project', back_populates='users') - role = db.Column(db.Integer, nullable=False) - - # todo: figure out where to put the role property - - def user_as_dict(self): - return { 'user_id': self.user_id, 'role': self.role } - - def project_as_dict(self): - return { 'project_id': self.project_id, 'role': self.role } +from api.models.userHasProjectModel import UserHasProject +from api.models.userLinkModel import UserLink class User(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -42,21 +30,3 @@ def as_dict(self): def __repr__(self): return '' % self.name - -class UserLink(db.Model): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80), nullable=False) - url = db.Column(db.Text, nullable=False) - user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) - - def as_dict(self): - obj_d = { - 'id': self.id, - 'name': self.name, - 'url': self.url, - 'user_id': self.user_id - } - return obj_d - - def __repr__(self): - return '' % self.name \ No newline at end of file From aa5b9b6d3c506e95642b353fd1095e5783f043e1 Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 12 Apr 2020 10:56:58 +0200 Subject: [PATCH 06/14] Implemented update route for User and Project. --- src/api/controllers/projectController.py | 13 +++++++++++++ src/api/controllers/userController.py | 13 +++++++++++++ src/api/views/projectView.py | 8 ++++++++ src/api/views/userView.py | 12 ++++++++++-- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/api/controllers/projectController.py b/src/api/controllers/projectController.py index bfdaebe..cdb4a1e 100644 --- a/src/api/controllers/projectController.py +++ b/src/api/controllers/projectController.py @@ -9,6 +9,19 @@ def create_project(self, **kwargs): return project + def update_project(self, id, **kwargs): + project = Project.query.filter_by(id=id).first() + + if project == None: + return project + + for key, value in kwargs.items(): + setattr(project, key, value) + + db.session.commit() + + return project + def get_project(self, **kwargs): project = Project.query.filter_by(**kwargs).first() diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index d2ff85d..fba76e8 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -8,6 +8,19 @@ def create_user(self, **kwargs): self.session.commit() return user + + def update_user(self, id, **kwargs): + user = User.query.filter_by(id=id).first() + + if user == None: + return user + + for key, value in kwargs.items(): + setattr(user, key, value) + + db.session.commit() + + return user def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() diff --git a/src/api/views/projectView.py b/src/api/views/projectView.py index 584a1fa..994f2dd 100644 --- a/src/api/views/projectView.py +++ b/src/api/views/projectView.py @@ -8,6 +8,14 @@ def post_project(): return jsonify(project.as_dict()), 201 +@app.route("/projects/", methods=['POST']) +def update_project(id): + if 'id' in request.get_json(): + return "", 501 + project = projectController.update_project(id, **request.get_json()) + + return jsonify(project.as_dict()), 200 + @app.route("/projects/", methods=['GET']) def get_project(id): project = projectController.get_project(id=id) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 60e51cb..b07d321 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -3,11 +3,19 @@ from api.controllers import userController @app.route("/users", methods=['POST']) -def post_user(): +def create_user(): user = userController.create_user(**request.get_json()) return jsonify(user.as_dict()), 201 +@app.route("/users/", methods=['POST']) +def update_user(id): + if 'id' in request.get_json(): + return "", 501 + user = userController.update_user(id, **request.get_json()) + + return jsonify(user.as_dict()), 200 + @app.route("/users/", methods=['GET']) def get_user(id): user = userController.get_user(id=id) @@ -30,6 +38,6 @@ def delete_user(id): user = userController.delete_user(id) if user: - return "", 202 + return "", 200 else: return "", 404 \ No newline at end of file From 00f484a24e60995364e20bd6ac1a984575df2c06 Mon Sep 17 00:00:00 2001 From: petak5 Date: Fri, 3 Apr 2020 21:21:18 +0200 Subject: [PATCH 07/14] Added Flask Marshmallow to the project, implemented get_all_users endpoint. --- src/api/__init__.py | 2 ++ src/api/controllers/userController.py | 4 ++++ src/api/models/userModel.py | 5 +++++ src/api/views/userView.py | 17 +++++++++++++---- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/api/__init__.py b/src/api/__init__.py index 6c88e10..39c05cb 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -3,7 +3,9 @@ """ from flask import Flask +from flask_marshmallow import Marshmallow app = Flask(__name__) +ma = Marshmallow(app) from api.models import db import api.models diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index a7806d2..7daec95 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -10,5 +10,9 @@ def create_user(self, **kwargs): def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() return user + + def get_all_users(self, **kwargs): + all_users = User.query.all() + return all_users userController = UserController() diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 389d5e6..4629d45 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -1,3 +1,4 @@ +from api import ma from api.models import db class UserHasProject(db.Model): @@ -20,6 +21,10 @@ class User(db.Model): def __repr__(self): return '' % self.name + +class UserSchema(ma.Schema): + class Meta: + fields = ('id', 'name') class UserLink(db.Model): id = db.Column(db.Integer, primary_key=True) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 4107d5b..54fa58e 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,7 +1,10 @@ +from flask import request, jsonify from api import app - from api.controllers import userController -from flask import request +from api.models.userModel import UserSchema + +userSchema = UserSchema() +usersSchema = UserSchema(many=True) @app.route("/user/push", methods=['POST']) def push_user(): @@ -10,5 +13,11 @@ def push_user(): @app.route("/user/get/", methods=['GET']) def get_user(name): - user = userController.get_user(username=name) - return user.username + user = userController.get_user(name=name) + return user.name + +@app.route("/users", methods=['GET']) +def get_all_users(): + all_users = userController.get_all_users() + + return jsonify(usersSchema.dump(all_users)) \ No newline at end of file From 273587604cc48cefa47b3ca8824d6157b4265dde Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 5 Apr 2020 13:27:04 +0200 Subject: [PATCH 08/14] Fixed User's get and post routes and added a delete route. --- src/api/controllers/userController.py | 11 ++++++++- src/api/views/userView.py | 32 +++++++++++++++++++-------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index 7daec95..7ff89a8 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -7,12 +7,21 @@ def create_user(self, **kwargs): self.session.add(user) self.session.commit() + return user + def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() + return user - + def get_all_users(self, **kwargs): all_users = User.query.all() + return all_users + def delete_user(self, id): + result = User.query.filter_by(id=id).delete() + db.session.commit() + return result + userController = UserController() diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 54fa58e..1cdb491 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -6,18 +6,32 @@ userSchema = UserSchema() usersSchema = UserSchema(many=True) -@app.route("/user/push", methods=['POST']) -def push_user(): - user = userController.create_user(**request.form) - return "200OK" +@app.route("/users", methods=['POST']) +def post_user(): + user = userController.create_user(**request.get_json()) -@app.route("/user/get/", methods=['GET']) -def get_user(name): - user = userController.get_user(name=name) - return user.name + return jsonify(userSchema.dump(user)), 201 + +@app.route("/users/", methods=['GET']) +def get_user(id): + user = userController.get_user(id=id) + + if user: + return jsonify(userSchema.dump(user)), 200 + else: + return "", 404 @app.route("/users", methods=['GET']) def get_all_users(): all_users = userController.get_all_users() - return jsonify(usersSchema.dump(all_users)) \ No newline at end of file + return jsonify(usersSchema.dump(all_users)), 200 + +@app.route("/users/", methods=['DELETE']) +def delete_user(id): + result = userController.delete_user(id) + + if result: + return "", 202 + else: + return "", 404 \ No newline at end of file From 3d6e16cabda646f2adffd3c2729107db125031cc Mon Sep 17 00:00:00 2001 From: petak5 Date: Sat, 11 Apr 2020 20:37:14 +0200 Subject: [PATCH 09/14] Removed Flask Marshmallow and replaced it with manual iterating over model properties. Fixed users delete route. --- src/api/__init__.py | 4 +-- src/api/controllers/userController.py | 20 ++++++++++++--- src/api/models/projectModel.py | 23 +++++++++++++++++ src/api/models/userModel.py | 36 +++++++++++++++++++++++---- src/api/views/userView.py | 16 ++++++------ 5 files changed, 80 insertions(+), 19 deletions(-) diff --git a/src/api/__init__.py b/src/api/__init__.py index 39c05cb..312906b 100644 --- a/src/api/__init__.py +++ b/src/api/__init__.py @@ -3,9 +3,9 @@ """ from flask import Flask -from flask_marshmallow import Marshmallow app = Flask(__name__) -ma = Marshmallow(app) +# Disable sorting of the jsonified data +app.config['JSON_SORT_KEYS'] = False from api.models import db import api.models diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index 7ff89a8..d2ff85d 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -1,4 +1,4 @@ -from api.models import db, User +from api.models import db, User, UserHasProject, UserLink class UserController: session = db.session() @@ -20,8 +20,22 @@ def get_all_users(self, **kwargs): return all_users def delete_user(self, id): - result = User.query.filter_by(id=id).delete() + # Remove all user's links + for link in UserLink.query.filter_by(user_id=id).all(): + db.session.delete(link) + + # Remove user from all projects + for project in UserHasProject.query.filter_by(user_id=id).all(): + db.session.delete(project) + + user = User.query.filter_by(id=id).first() + + if user == None: + return user + + db.session.delete(user) db.session.commit() - return result + + return user userController = UserController() diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index 04be1fa..ec0d717 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -11,6 +11,19 @@ class Project(db.Model): users = db.relationship('UserHasProject', back_populates='project') links = db.relationship('ProjectLink', backref='project', lazy=True) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'description': self.description, + 'languages': self.languages, + 'development_status': self.development_status, + 'creation_date': self.creation_date, + 'release_date': self.release_date, + 'links': [ link.as_dict() for link in self.links ] + } + return obj_d + def __repr__(self): return '' % self.name @@ -20,5 +33,15 @@ class ProjectLink(db.Model): url = db.Column(db.Text, nullable=False) project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) + # todo: decide if this should contain project_id (it is already present in the model) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'project_id': self.project_id + } + return obj_d + def __repr__(self): return '' % self.name \ No newline at end of file diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 4629d45..8601226 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -1,4 +1,3 @@ -from api import ma from api.models import db class UserHasProject(db.Model): @@ -8,6 +7,14 @@ class UserHasProject(db.Model): project = db.relationship('Project', back_populates='users') role = db.Column(db.Integer, nullable=False) + # todo: figure out where to put the role property + + def user_as_dict(self): + return self.user.as_dict() + + def project_as_dict(self): + return self.project.as_dict() + class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) @@ -19,12 +26,22 @@ class User(db.Model): projects = db.relationship('UserHasProject', back_populates='user') links = db.relationship('UserLink', backref='user', lazy=True) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'bio': self.bio, + 'languages': self.languages, + 'interests': self.interests, + 'location': self.location, + 'occupation': self.occupation, + 'projects': [ project.project_as_dict() for project in self.projects ], + 'links': [ link.as_dict() for link in self.links ] + } + return obj_d + def __repr__(self): return '' % self.name - -class UserSchema(ma.Schema): - class Meta: - fields = ('id', 'name') class UserLink(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -32,5 +49,14 @@ class UserLink(db.Model): url = db.Column(db.Text, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'user_id': self.user_id + } + return obj_d + def __repr__(self): return '' % self.name \ No newline at end of file diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 1cdb491..60e51cb 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -1,23 +1,19 @@ from flask import request, jsonify from api import app from api.controllers import userController -from api.models.userModel import UserSchema - -userSchema = UserSchema() -usersSchema = UserSchema(many=True) @app.route("/users", methods=['POST']) def post_user(): user = userController.create_user(**request.get_json()) - return jsonify(userSchema.dump(user)), 201 + return jsonify(user.as_dict()), 201 @app.route("/users/", methods=['GET']) def get_user(id): user = userController.get_user(id=id) if user: - return jsonify(userSchema.dump(user)), 200 + return jsonify(user.as_dict()), 200 else: return "", 404 @@ -25,13 +21,15 @@ def get_user(id): def get_all_users(): all_users = userController.get_all_users() - return jsonify(usersSchema.dump(all_users)), 200 + users = [ user.as_dict() for user in all_users ] + + return jsonify(users), 200 @app.route("/users/", methods=['DELETE']) def delete_user(id): - result = userController.delete_user(id) + user = userController.delete_user(id) - if result: + if user: return "", 202 else: return "", 404 \ No newline at end of file From 05f21b5847d2f7905ea3d7202db9dfe34a5b4cbf Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 12 Apr 2020 09:52:54 +0200 Subject: [PATCH 10/14] Implemented Project routes. --- src/api/controllers/projectController.py | 31 +++++++++++++++++++-- src/api/models/projectModel.py | 6 ++-- src/api/models/userModel.py | 4 +-- src/api/views/__init__.py | 2 +- src/api/views/projectView.py | 35 ++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 src/api/views/projectView.py diff --git a/src/api/controllers/projectController.py b/src/api/controllers/projectController.py index 6d4982e..bfdaebe 100644 --- a/src/api/controllers/projectController.py +++ b/src/api/controllers/projectController.py @@ -1,4 +1,4 @@ -from api.models import db, Project +from api.models import db, Project, UserHasProject, ProjectLink class ProjectController: session = db.session() @@ -7,8 +7,35 @@ def create_project(self, **kwargs): self.session.add(project) self.session.commit() + return project + def get_project(self, **kwargs): project = Project.query.filter_by(**kwargs).first() + + return project + + def get_all_projects(self, **kwargs): + all_projects = Project.query.all() + + return all_projects + + def delete_project(self, id): + # Remove all project's links + for link in ProjectLink.query.filter_by(project_id=id).all(): + db.session.delete(link) + + # Remove project from all users + for project in UserHasProject.query.filter_by(project_id=id).all(): + db.session.delete(project) + + project = Project.query.filter_by(id=id).first() + + if project == None: + return project + + db.session.delete(project) + db.session.commit() + return project -projectController = ProjectController() +projectController = ProjectController() \ No newline at end of file diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index ec0d717..4625394 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -1,12 +1,13 @@ from api.models import db +from datetime import datetime class Project(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) description = db.Column(db.Text, nullable=False) languages = db.Column(db.Text) - development_status = db.Column(db.Integer, nullable=False) - creation_date = db.Column(db.DateTime, nullable=False) + development_status = db.Column(db.Integer, nullable=False, default=0) + creation_date = db.Column(db.DateTime, nullable=False, default=datetime.now()) release_date = db.Column(db.DateTime) users = db.relationship('UserHasProject', back_populates='project') links = db.relationship('ProjectLink', backref='project', lazy=True) @@ -20,6 +21,7 @@ def as_dict(self): 'development_status': self.development_status, 'creation_date': self.creation_date, 'release_date': self.release_date, + 'users': [ user.user_as_dict() for user in self.users ], 'links': [ link.as_dict() for link in self.links ] } return obj_d diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 8601226..d18ca83 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -10,10 +10,10 @@ class UserHasProject(db.Model): # todo: figure out where to put the role property def user_as_dict(self): - return self.user.as_dict() + return { 'user_id': self.user_id, 'role': self.role } def project_as_dict(self): - return self.project.as_dict() + return { 'project_id': self.project_id, 'role': self.role } class User(db.Model): id = db.Column(db.Integer, primary_key=True) diff --git a/src/api/views/__init__.py b/src/api/views/__init__.py index 82faa16..8820895 100644 --- a/src/api/views/__init__.py +++ b/src/api/views/__init__.py @@ -1,4 +1,4 @@ """ The views package """ -from api.views import userView, oauthView \ No newline at end of file +from api.views import userView, projectView, oauthView diff --git a/src/api/views/projectView.py b/src/api/views/projectView.py new file mode 100644 index 0000000..584a1fa --- /dev/null +++ b/src/api/views/projectView.py @@ -0,0 +1,35 @@ +from flask import request, jsonify +from api import app +from api.controllers import projectController + +@app.route("/projects", methods=['POST']) +def post_project(): + project = projectController.create_project(**request.get_json()) + + return jsonify(project.as_dict()), 201 + +@app.route("/projects/", methods=['GET']) +def get_project(id): + project = projectController.get_project(id=id) + + if project: + return jsonify(project.as_dict()), 200 + else: + return "", 404 + +@app.route("/projects", methods=['GET']) +def get_all_projects(): + all_projects = projectController.get_all_projects() + + projects = [ project.as_dict() for project in all_projects ] + + return jsonify(projects), 200 + +@app.route("/projects/", methods=['DELETE']) +def delete_project(id): + project = projectController.delete_project(id) + + if project: + return "", 202 + else: + return "", 404 \ No newline at end of file From 994cdf91452ebf44b116661cd06031fb14c9d5c6 Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 12 Apr 2020 10:12:09 +0200 Subject: [PATCH 11/14] Moved models to separate files. --- src/api/models/__init__.py | 9 +++++-- src/api/models/projectLinkModel.py | 20 ++++++++++++++++ src/api/models/projectModel.py | 22 +++-------------- src/api/models/userHasProjectModel.py | 14 +++++++++++ src/api/models/userLinkModel.py | 19 +++++++++++++++ src/api/models/userModel.py | 34 ++------------------------- 6 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 src/api/models/projectLinkModel.py create mode 100644 src/api/models/userHasProjectModel.py create mode 100644 src/api/models/userLinkModel.py diff --git a/src/api/models/__init__.py b/src/api/models/__init__.py index 13a7a3c..e160639 100644 --- a/src/api/models/__init__.py +++ b/src/api/models/__init__.py @@ -3,9 +3,14 @@ """ from sys import argv from datetime import datetime + from api.models.database import db, init_db -from api.models.userModel import UserHasProject, User, UserLink -from api.models.projectModel import Project, ProjectLink + +from api.models.userModel import User +from api.models.userLinkModel import UserLink +from api.models.projectModel import Project +from api.models.projectLinkModel import ProjectLink +from api.models.userHasProjectModel import UserHasProject if '--reset-db' in argv: init_db(True) diff --git a/src/api/models/projectLinkModel.py b/src/api/models/projectLinkModel.py new file mode 100644 index 0000000..929d528 --- /dev/null +++ b/src/api/models/projectLinkModel.py @@ -0,0 +1,20 @@ +from api.models import db + +class ProjectLink(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + url = db.Column(db.Text, nullable=False) + project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) + + # todo: decide if this should contain project_id (it is already present in the model) + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'project_id': self.project_id + } + return obj_d + + def __repr__(self): + return '' % self.name diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index 4625394..b5cfa15 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -1,6 +1,9 @@ from api.models import db from datetime import datetime +from api.models.userHasProjectModel import UserHasProject +from api.models.projectLinkModel import ProjectLink + class Project(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) @@ -28,22 +31,3 @@ def as_dict(self): def __repr__(self): return '' % self.name - -class ProjectLink(db.Model): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80), nullable=False) - url = db.Column(db.Text, nullable=False) - project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) - - # todo: decide if this should contain project_id (it is already present in the model) - def as_dict(self): - obj_d = { - 'id': self.id, - 'name': self.name, - 'url': self.url, - 'project_id': self.project_id - } - return obj_d - - def __repr__(self): - return '' % self.name \ No newline at end of file diff --git a/src/api/models/userHasProjectModel.py b/src/api/models/userHasProjectModel.py new file mode 100644 index 0000000..5bc446e --- /dev/null +++ b/src/api/models/userHasProjectModel.py @@ -0,0 +1,14 @@ +from api.models import db + +class UserHasProject(db.Model): + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) + project_id = db.Column(db.Integer, db.ForeignKey('project.id'), primary_key=True) + user = db.relationship('User', back_populates='projects') + project = db.relationship('Project', back_populates='users') + role = db.Column(db.Integer, nullable=False) + + def user_as_dict(self): + return { 'user_id': self.user_id, 'role': self.role } + + def project_as_dict(self): + return { 'project_id': self.project_id, 'role': self.role } diff --git a/src/api/models/userLinkModel.py b/src/api/models/userLinkModel.py new file mode 100644 index 0000000..64fa5fa --- /dev/null +++ b/src/api/models/userLinkModel.py @@ -0,0 +1,19 @@ +from api.models import db + +class UserLink(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(80), nullable=False) + url = db.Column(db.Text, nullable=False) + user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) + + def as_dict(self): + obj_d = { + 'id': self.id, + 'name': self.name, + 'url': self.url, + 'user_id': self.user_id + } + return obj_d + + def __repr__(self): + return '' % self.name diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index d18ca83..8214414 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -1,19 +1,7 @@ from api.models import db -class UserHasProject(db.Model): - user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) - project_id = db.Column(db.Integer, db.ForeignKey('project.id'), primary_key=True) - user = db.relationship('User', back_populates='projects') - project = db.relationship('Project', back_populates='users') - role = db.Column(db.Integer, nullable=False) - - # todo: figure out where to put the role property - - def user_as_dict(self): - return { 'user_id': self.user_id, 'role': self.role } - - def project_as_dict(self): - return { 'project_id': self.project_id, 'role': self.role } +from api.models.userHasProjectModel import UserHasProject +from api.models.userLinkModel import UserLink class User(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -42,21 +30,3 @@ def as_dict(self): def __repr__(self): return '' % self.name - -class UserLink(db.Model): - id = db.Column(db.Integer, primary_key=True) - name = db.Column(db.String(80), nullable=False) - url = db.Column(db.Text, nullable=False) - user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) - - def as_dict(self): - obj_d = { - 'id': self.id, - 'name': self.name, - 'url': self.url, - 'user_id': self.user_id - } - return obj_d - - def __repr__(self): - return '' % self.name \ No newline at end of file From 319f25b376250f7629510b6eec82a057e813154c Mon Sep 17 00:00:00 2001 From: petak5 Date: Sun, 12 Apr 2020 10:56:58 +0200 Subject: [PATCH 12/14] Implemented update route for User and Project. --- src/api/controllers/projectController.py | 13 +++++++++++++ src/api/controllers/userController.py | 13 +++++++++++++ src/api/views/projectView.py | 8 ++++++++ src/api/views/userView.py | 12 ++++++++++-- 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/api/controllers/projectController.py b/src/api/controllers/projectController.py index bfdaebe..cdb4a1e 100644 --- a/src/api/controllers/projectController.py +++ b/src/api/controllers/projectController.py @@ -9,6 +9,19 @@ def create_project(self, **kwargs): return project + def update_project(self, id, **kwargs): + project = Project.query.filter_by(id=id).first() + + if project == None: + return project + + for key, value in kwargs.items(): + setattr(project, key, value) + + db.session.commit() + + return project + def get_project(self, **kwargs): project = Project.query.filter_by(**kwargs).first() diff --git a/src/api/controllers/userController.py b/src/api/controllers/userController.py index d2ff85d..fba76e8 100644 --- a/src/api/controllers/userController.py +++ b/src/api/controllers/userController.py @@ -8,6 +8,19 @@ def create_user(self, **kwargs): self.session.commit() return user + + def update_user(self, id, **kwargs): + user = User.query.filter_by(id=id).first() + + if user == None: + return user + + for key, value in kwargs.items(): + setattr(user, key, value) + + db.session.commit() + + return user def get_user(self, **kwargs): user = User.query.filter_by(**kwargs).first() diff --git a/src/api/views/projectView.py b/src/api/views/projectView.py index 584a1fa..994f2dd 100644 --- a/src/api/views/projectView.py +++ b/src/api/views/projectView.py @@ -8,6 +8,14 @@ def post_project(): return jsonify(project.as_dict()), 201 +@app.route("/projects/", methods=['POST']) +def update_project(id): + if 'id' in request.get_json(): + return "", 501 + project = projectController.update_project(id, **request.get_json()) + + return jsonify(project.as_dict()), 200 + @app.route("/projects/", methods=['GET']) def get_project(id): project = projectController.get_project(id=id) diff --git a/src/api/views/userView.py b/src/api/views/userView.py index 60e51cb..b07d321 100644 --- a/src/api/views/userView.py +++ b/src/api/views/userView.py @@ -3,11 +3,19 @@ from api.controllers import userController @app.route("/users", methods=['POST']) -def post_user(): +def create_user(): user = userController.create_user(**request.get_json()) return jsonify(user.as_dict()), 201 +@app.route("/users/", methods=['POST']) +def update_user(id): + if 'id' in request.get_json(): + return "", 501 + user = userController.update_user(id, **request.get_json()) + + return jsonify(user.as_dict()), 200 + @app.route("/users/", methods=['GET']) def get_user(id): user = userController.get_user(id=id) @@ -30,6 +38,6 @@ def delete_user(id): user = userController.delete_user(id) if user: - return "", 202 + return "", 200 else: return "", 404 \ No newline at end of file From 09ffce4ce1991e57f79deecae420a1d29a30ee01 Mon Sep 17 00:00:00 2001 From: marter11 Date: Tue, 28 Apr 2020 15:14:35 +0300 Subject: [PATCH 13/14] feedback entities and relations --- src/api/models/__init__.py | 24 +++++++++++++++++++++--- src/api/models/projectModel.py | 11 ++++++++++- src/api/models/userModel.py | 13 ++++++++++++- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/api/models/__init__.py b/src/api/models/__init__.py index 13a7a3c..cffd0f3 100644 --- a/src/api/models/__init__.py +++ b/src/api/models/__init__.py @@ -4,8 +4,8 @@ from sys import argv from datetime import datetime from api.models.database import db, init_db -from api.models.userModel import UserHasProject, User, UserLink -from api.models.projectModel import Project, ProjectLink +from api.models.userModel import UserHasProject, User, UserLink, UserFeedback +from api.models.projectModel import Project, ProjectLink, ProjectFeedback if '--reset-db' in argv: init_db(True) @@ -17,10 +17,12 @@ import datetime; user1 = User(name='Foe Joe') +user2 = User(name='Tommy Frich') +user3 = User(name='Limm Carter') link1 = UserLink(name='GitHub', url='https://github.com') user1.links.append(link1) -project1 = Project(name='Hello, World!', description='First project.', development_status=2, creation_date=datetime.datetime.now()) +project1 = Project(name='Hello, World!', repository="https://github.com/ProgrammingBuddies/programmingbuddies-api", description='First project.', development_status=2, creation_date=datetime.datetime.now()) link2 = ProjectLink(name='Reddit', url='https://reddit.com') project1.links.append(link2) @@ -29,6 +31,22 @@ user1.projects.append(userHasProject) +feedback1 = ProjectFeedback(rating=3, description="Cool project!", author=user1) +feedback2 = ProjectFeedback(rating=1, description="Not so cool!", author=user2) + +project1.feedbacks.append(feedback1) +project1.feedbacks.append(feedback2) + +feedback3 = UserFeedback(author=user1, user=user2, rating=5, description="Good guy!") +feedback4 = UserFeedback(author=user3, user=user2, rating=1, description="Poor guy!") + db.session.add(user1) +db.session.add(user2) +db.session.add(user3) db.session.commit() + +users = User.query.all() +print(users[0].author, users[0].user, users[0].project_feedbacks) +print(users[1].author, users[1].user, users[1].project_feedbacks) +print(users[2].author, users[2].user, users[2].project_feedbacks) """ diff --git a/src/api/models/projectModel.py b/src/api/models/projectModel.py index 04be1fa..71d7962 100644 --- a/src/api/models/projectModel.py +++ b/src/api/models/projectModel.py @@ -8,8 +8,10 @@ class Project(db.Model): development_status = db.Column(db.Integer, nullable=False) creation_date = db.Column(db.DateTime, nullable=False) release_date = db.Column(db.DateTime) + repository = db.Column(db.Text, nullable=False) users = db.relationship('UserHasProject', back_populates='project') links = db.relationship('ProjectLink', backref='project', lazy=True) + feedbacks = db.relationship('ProjectFeedback', backref='project') def __repr__(self): return '' % self.name @@ -21,4 +23,11 @@ class ProjectLink(db.Model): project_id = db.Column(db.Integer, db.ForeignKey('project.id'), nullable=False) def __repr__(self): - return '' % self.name \ No newline at end of file + return '' % self.name + +class ProjectFeedback(db.Model): + id = db.Column(db.Integer, primary_key=True) + user_id = db.Column(db.Integer, db.ForeignKey('user.id')) + project_id = db.Column(db.Integer, db.ForeignKey('project.id')) + rating = db.Column(db.Integer, nullable=False) + description = db.Column(db.String(255), nullable=True) diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index 389d5e6..5190b81 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -17,6 +17,7 @@ class User(db.Model): occupation = db.Column(db.String(80)) projects = db.relationship('UserHasProject', back_populates='user') links = db.relationship('UserLink', backref='user', lazy=True) + project_feedbacks = db.relationship('ProjectFeedback', backref='author') def __repr__(self): return '' % self.name @@ -28,4 +29,14 @@ class UserLink(db.Model): user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) def __repr__(self): - return '' % self.name \ No newline at end of file + return '' % self.name + +class UserFeedback(db.Model): + id = db.Column(db.Integer, primary_key=True) + author_id = db.Column(db.Integer, db.ForeignKey('user.id')) + user_id = db.Column(db.Integer, db.ForeignKey('user.id')) + rating = db.Column(db.Integer, nullable=False) + description = db.Column(db.String(255), nullable=True) + + author = db.relationship('User', foreign_keys=[author_id], backref='author') + user = db.relationship('User', foreign_keys=[user_id], backref='user') From 2e3dbf0953494136a0c9c604dc7ac2fb53d5befc Mon Sep 17 00:00:00 2001 From: marter11 Date: Wed, 13 May 2020 14:51:26 +0300 Subject: [PATCH 14/14] ProjectFeedback model fix v --- src/api/models/__init__.py | 13 ++++--------- src/api/models/projectFeedbackModel.py | 2 -- src/api/models/userFeedbackModel.py | 3 --- src/api/models/userModel.py | 4 +++- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/api/models/__init__.py b/src/api/models/__init__.py index cf13fbc..57cc9a3 100644 --- a/src/api/models/__init__.py +++ b/src/api/models/__init__.py @@ -38,22 +38,17 @@ user1.projects.append(userHasProject) -feedback1 = ProjectFeedback(rating=3, description="Cool project!", author=user1) -feedback2 = ProjectFeedback(rating=1, description="Not so cool!", author=user2) +feedback1 = ProjectFeedback(rating=3, description="Cool project!", project_feed_author=user1, project=project1) +feedback2 = ProjectFeedback(rating=1, description="Not so cool!", project_feed_author=user2, project=project1) # project1.feedbacks.append(feedback1) # project1.feedbacks.append(feedback2) -feedback3 = UserFeedback(author=user1, user=user2, rating=5, description="Good guy!") -feedback4 = UserFeedback(author=user3, user=user2, rating=1, description="Poor guy!") +feedback3 = UserFeedback(user_feed_author=user1, destination=user2, rating=5, description="Good guy!") +feedback4 = UserFeedback(user_feed_author=user3, destination=user2, rating=1, description="Poor guy!") db.session.add(user1) db.session.add(user2) db.session.add(user3) db.session.commit() - -users = User.query.all() -print(users[0].author, users[0].user, users[0].project_feedbacks) -print(users[1].author, users[1].user, users[1].project_feedbacks) -print(users[2].author, users[2].user, users[2].project_feedbacks) """ diff --git a/src/api/models/projectFeedbackModel.py b/src/api/models/projectFeedbackModel.py index 25aa363..7e62061 100644 --- a/src/api/models/projectFeedbackModel.py +++ b/src/api/models/projectFeedbackModel.py @@ -1,6 +1,4 @@ from api.models import db -# from api.models.projectModel import Project -# from api.models.userModel import User class ProjectFeedback(db.Model): id = db.Column(db.Integer, primary_key=True) diff --git a/src/api/models/userFeedbackModel.py b/src/api/models/userFeedbackModel.py index 027cc9b..353111a 100644 --- a/src/api/models/userFeedbackModel.py +++ b/src/api/models/userFeedbackModel.py @@ -1,5 +1,4 @@ from api.models import db -# from api.models.userModel import User class UserFeedback(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -7,8 +6,6 @@ class UserFeedback(db.Model): user_id = db.Column(db.Integer, db.ForeignKey('user.id')) rating = db.Column(db.Integer, nullable=False) description = db.Column(db.String(255), nullable=True) - author = db.relationship('User', foreign_keys=[author_id], backref='author') - user = db.relationship('User', foreign_keys=[user_id], backref='user') def as_dict(self): obj_d = { diff --git a/src/api/models/userModel.py b/src/api/models/userModel.py index a0b7182..7084b32 100644 --- a/src/api/models/userModel.py +++ b/src/api/models/userModel.py @@ -14,7 +14,9 @@ class User(db.Model): occupation = db.Column(db.String(80)) projects = db.relationship('UserHasProject', back_populates='user') links = db.relationship('UserLink', backref='user', lazy=True) - project_feedbacks = db.relationship('ProjectFeedback', backref='author') + project_feedbacks = db.relationship('ProjectFeedback', backref='project_feed_author') + user_feedbacks = db.relationship('UserFeedback', foreign_keys="UserFeedback.author_id", backref='user_feed_author') + received_feebacks = db.relationship('UserFeedback', foreign_keys="UserFeedback.user_id", backref='destination') def as_dict(self): obj_d = {