Code Review Asked by amos-baron on November 21, 2021
I’m writing a simple REST API to my MongoDB using PyMongo (Python 3.7).
Each collection I have in the DB has a route (e.g http://the.api.url/collection_name ),
and every document under that collection has a sub-route (e.g http://the.api.url/collection_name/document_id ).
The micro-services in my program need to access this API in order to get stuff from the DB and upload stuff to it.
I feel like my code isn’t DRY enough but cant think of how to make it better.
from flask import Flask,jsonify,request
from flask_pymongo import PyMongo
from pymongo import errors
import os
app = Flask(__name__)
mongodb_ip = os.environ.get("DB_IP", "chaos.mongodb.openshift")
mongodb_port = os.environ.get("DB_PORT", "8080")
db_name = os.environ.get("DB_NAME", "chaos")
server_port = int(os.environ.get("SERVER_PORT", 5001))
mongodb_uri = "mongodb://{}:{}/{}".format(mongodb_ip,mongodb_port,db_name)
app.config['MONGODB_NAME'] = db_name
app.config['MONGO_URI'] = mongodb_uri
mongo = PyMongo(app)
@app.route('/servers',methods=['GET'])
@app.route('/server',methods=['GET'])
def get_all_servers():
collection = "servers"
expected_returned_keys = ["dns","active","groups"]
output = get_all_objects(collection, expected_returned_keys)
return output
@app.route('/servers/<dns>' ,methods=['GET'])
@app.route('/server/<dns>' ,methods=['GET'])
def get_one_server(dns):
collection = "servers"
identifier_key = "dns"
identifier_value = dns
expected_returned_keys = ["dns", "active","groups"]
output = get_one_object(collection,identifier_key,identifier_value,expected_returned_keys)
return output
@app.route('/servers', methods=['POST'])
@app.route('/server', methods=['POST'])
def add_server():
collection = "servers"
json_object = request.get_json()
expected_returned_keys = ["dns", "active","groups"]
identifier_key = "dns"
try :
identifier_value = json_object["dns"]
except KeyError :
return "dns is a required parameter",400
default_request_values = {'active' : False, 'groups' : [], 'last_fault' : '15:12:00:00:00:00'}
add_object_to_db(collection, json_object, expected_returned_keys, identifier_key, identifier_value,default_request_values)
@app.route('/groups', methods=['GET'])
@app.route('/group', methods=['GET'])
def get_all_groups():
collection = "groups"
expected_returned_keys = ["name", "active"]
output = get_all_objects(collection, expected_returned_keys)
return output
@app.route('/groups/<name>' ,methods=['GET'])
@app.route('/group/<name>' ,methods=['GET'])
def get_one_group(name):
collection = "groups"
identifier_key = "name"
identifier_value = name
expected_returned_keys = ["name", "active"]
output = get_one_object(collection, identifier_key, identifier_value, expected_returned_keys)
return output
@app.route('/groups', methods=['POST'])
@app.route('/group', methods=['POST'])
def add_group():
collection = "groups"
json_object = request.get_json()
expected_returned_keys = ["name", "active"]
identifier_key = "name"
try:
identifier_value = json_object["name"]
except KeyError:
return "name is a required parameter", 400
default_request_values = {'members' : [], 'active' : False}
output = add_object_to_db(collection, json_object, expected_returned_keys, identifier_key, identifier_value,default_request_values)
return output
output = add_object_to_db(collection, json_object, expected_returned_keys, identifier_key, identifier_value,default_request_values)
return output
@app.route('/logs', methods=['GET'])
@app.route('/log', methods=['GET'])
def get_all_logs():
collection = "logs"
expected_returned_keys = ["name", 'logs' , "date", "successful" ]
output = get_all_objects(collection, expected_returned_keys)
return output
@app.route('/logs/<name>' ,methods=['GET'])
@app.route('/log/<name>' ,methods=['GET'])
def get_one_log(name):
collection = "logs"
identifier_key = "name"
identifier_value = name
expected_returned_keys = ["name", 'logs' , "date", "successful" ]
output = get_one_object(collection, identifier_key, identifier_value, expected_returned_keys)
return output
def get_one_object(collection,identifier_key,identifier_value,expected_returned_keys):
# Easyiest way to use a string as a property of an object
objects = eval("mongo.db.{}".format(collection))
query = objects.find_one({identifier_key : identifier_value})
if query:
output = {}
for key in expected_returned_keys :
output[key] = query[key]
else :
output = "object not found"
return jsonify(output)
def get_all_objects(collection,expected_returned_keys):
# Easyiest way to use a string as a property of an object
objects = eval("mongo.db.{}".format(collection))
output = []
for query in objects.find():
found_object = {}
for key in expected_returned_keys :
found_object[key] = query[key]
output.append(found_object)
return jsonify({'result' : output})
def add_object_to_db(collection,json_object,expected_returned_keys,identifier_key,identifier_value,default_request_values):
# Easyiest way to use a string as a property of an object
objects = eval("mongo.db.{}".format(collection))
# Fill out default values if not in sent object
json_object = parse_json_object(json_object, default_request_values)
try:
if objects.count_documents({identifier_key: identifier_value}) > 0:
return {"result" : "object with the same identifier already exists"}, 400
else:
new_object_id = objects.insert(json_object, check_keys=False)
query = objects.find_one({'_id': new_object_id})
except (errors.WriteError, TypeError) as E:
print(E)
return jsonify({'result': 'the object failed the validation schema'}), 400
output = {}
for expected_key in expected_returned_keys:
output[expected_key] = query[expected_key]
return jsonify({'result': output})
def parse_json_object(json_object,default_values_dict):
default_keys = default_values_dict.keys()
object_keys = json_object.keys()
for default_key in default_keys:
if default_key not in object_keys :
json_object[default_key] = default_values_dict[default_key]
return json_object
if __name__ == '__main__':
app.run(host='0.0.0.0' , port=server_port)
```
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP