TransWikia.com

Simple Flask REST API to a MongoDB

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)

``` 

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP