How to create new routes dynamically python/flask

Asked

Viewed 892 times

2

I am developing an application that makes predictions from models, and wanted to implement a feature that allows me to create new routes through a function.

config = json.loads(open('config.json').read())

def create_models(config):
    for key, val in config.items():
        globals()[key] = initialize_model(val)

@app.route('/predict1', methods=['GET', 'POST'])
def predict1():
        if request.method == 'POST':
                try:
                        information= request.data
                except Exception as e:
                        print(e)
                        return abort(400, e)

                try:
                        results_inventory = predict1.pred(information)
                        inventory = set_inventory(results_inventory)
                        return jsonify(inventory)
                except Exception as e:
                        print(e)
                        return abort(500, e)

Everything is working as desired, config loads my JSON with the necessary information, create_models carries my models, predict1 receives the information and returns the results of the analysis.

I happen to have more than one model and wanted to provide a new route for each of them, here an example of my config.json:

{
    "predict1":
    {
        "model": "cfg/configurationfile1.txt",
        "load": 115,
        "threshold": 0.25,
    },

    "predict2":
    {
        "model": "cfg/configurationfile2.txt",
        "load": 600,
        "threshold": 0.10,

    }

}

As I have two models inside my config.json, I needed to create a new route manually, which is identical to the first one by changing only the places of the code where they appear predict1 for predict2. Stayed like this:

@app.route('/predict1', methods=['GET', 'POST'])
    def predict1():
            if request.method == 'POST':
                    try:
                            information= request.data
                    except Exception as e:
                            print(e)
                            return abort(400, e)

                    try:
                            results_inventory = predict1.pred(information)
                            inventory = set_inventory(results_inventory)
                            return jsonify(inventory)
                    except Exception as e:
                            print(e)
                            return abort(500, e)

@app.route('/predict2', methods=['GET', 'POST'])
    def predict2():
            if request.method == 'POST':
                    try:
                            information= request.data
                    except Exception as e:
                            print(e)
                            return abort(400, e)

                    try:
                            results_inventory = predict2.pred(information)
                            inventory = set_inventory(results_inventory)
                            return jsonify(inventory)
                    except Exception as e:
                            print(e)
                            return abort(500, e)

There is a way to automate this route creation process, so the script itself generates a new route whenever a new configuration appears in my JSON?

  • I don’t know if I got your problem right. Do you want to read the JSON file at the beginning and then create the routes? Or after creating the routes, depending on what users call, create new routes based on what is in the JSON file?

  • Hello Victor, I wish to create routes from the contents of my JSON.

  • So the answer below should be what you want or something very close to it.

1 answer

3


Before the if request.method == 'POST': is unnecessary, it would be enough to remove the GET from the above and hence no longer needs the if.

I think you can do it like this:

def pega_dados():
    import json
    with open('config.json') as f:
        return json.load(f)

@app.route('/<key>', methods = ['POST'])
def predict(key):
    config = pega_dados()
    try:
        model = config[key]['model']
        load = config[key]['load']
        threshold = config[key]['threshold']
    except Exception as e:
        print(e)
        return abort(404, e)

    try:
        information = request.data
    except Exception as e:
        print(e)
        return abort(400, e)

    try:
        results_inventory = predict.pred(information)
        inventory = set_inventory(results_inventory)
        return jsonify(inventory)
   except Exception as e:
        print(e)
        return abort(500, e)

However, I don’t think that predict.pred will do what you want, just as the predict1.pred and the predict2.pred of your original code. I think this was supposed to be something different. Anyway, at this point you should already have the model, the load and the threshold.

If the key the request is not inside the settings file, the result will be a 404.

Also note that if for some reason your JSON is changed at runtime, the routes will respond to this automatically. If you prefer them to be loaded only once at the beginning, avoiding having to reread them at each request, you can put the config = pega_dados() out of function.

  • You are right Victor the predict1.Pred is spelled wrong, in my code has already been changed to globals()['predict1' + 'model']. The pega_data() function you defined has some advantage over config = json.loads(open('config.json').read()) because I find the second syntax more elegant. Thank you very much solved the whole problem with <key>, I didn’t know this syntax.

  • @Filipegonçalves Is that using config = json.loads(open('config.json').read()), the open file will not be closed. It is only closed with an explicit call to close() or implicitly using the block with.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.