14

I got a doubt about how to pass an object to a flask app in the correct way.

The idea is simple.

I wan to create an api for my application, which means that http requests processed by my flask application will trigger methods in my main application.

For that, I need flask to be aware of my other process, one way or another.

Currently, I have something like :

if __name__ == '__main__':
    Logger = MyProcess()
    app.run()

I need to be able to do something like that :

@app.route('/nb_trendy')
def nb_trendy():

    res = Logger.get_trendy()
    return jsonify(res)

which means that I either need to either give a handle on Logger to app, or directly define Logger inside app.

But in each of the solutions I can find, I need to create a class that inherits app, to either override __init__() and takes objects as parameters, or modify the run() method.

the current way I would do it is though :

class MyFlask(Flask):
    def __init__():
        Flask.__init__()
        Logger = MyProcess()

Is this also the way you would do it, or is there a better way to do this?

Thanks!

Here is a more general version of this question: Web API in Flask

jlengrand
  • 12,152
  • 14
  • 57
  • 87

2 Answers2

19

Take a look at application factories, which should do what you're looking for. You'd create a factory that returned your Flask app that you'd send the logger to - something like this:

def create_app(logger_instance):
    app = Flask(__name__)
    app.config['LOGGER'] = logger_instance
    return app

And then in your runserver.py, you'd create and pass in the logger:

from yourapp import create_app
if __name__ == '__main__':
    logger = MyProcess()
    app = create_app(logger)
    app.run()

Once that's done, your app can refer to the logger inside app.config['LOGGER'].

girasquid
  • 15,121
  • 2
  • 48
  • 58
  • 1
    Is it really okay to put a class instance in `app.config`? It feels hacky. But admittedly, it is simple and easy to understand ("it's tied to the app"). – Nuclear03020704 Mar 19 '21 at 15:29
1

You might want to use flask app context for this

from flask import _app_ctx_stack 

def getLogger():
    appContext = _app_ctx_stack.top
    logger = getattr(appContext, "Logger", None)
    if logger is None:
        logger = MyProcess()
        appContext.Logger = logger
    return logger

....

@app.route('/nb_trendy')
def nb_trendy():
    logger = getLogger()
    res = logger.get_trendy()
    return jsonify(res)

more insight from Armin on that: https://speakerdeck.com/mitsuhiko/advanced-flask-patterns

mderk
  • 796
  • 4
  • 13