2
\$\begingroup\$

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)

``` 
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Welcome to Code Review. Please state the purpose of the code. What prompted you to write this? You wrote an API, to do what? Why? \$\endgroup\$ Commented Jul 22, 2020 at 11:23
  • \$\begingroup\$ @Mast just updated the intro, is this what you expected? \$\endgroup\$ Commented Jul 22, 2020 at 11:46
  • \$\begingroup\$ For what Python version did you write this? \$\endgroup\$ Commented Jul 22, 2020 at 12:34
  • 1
    \$\begingroup\$ @Mast python 3.7 \$\endgroup\$ Commented Jul 22, 2020 at 13:15

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.