Search code examples
pythonflask

Using flask inside class


I have an application with many threads. One of them is flask, which is used to implement (auxiliary) API. It's used with low load and never exposed to the Internet, so build-in flask web server is perfectly fine.

My current code looks like this:

class API:
    # ... all other stuff here, skipped
    def run():
        app = flask.Flask('API')

        @app.route('/cmd1')
        def cmd1():
            self.cmd1()

        @app.route('/cmd2')
        def cmd2()
            self.cmd2()

        app.run()

I feel I done it wrong, because all docs says 'create flask app at module level'. But I don't want to do this - it messes up with my tests, and API is a small part of the larger application, which has own structure and conventions (each 'application' is a separate class running in one or more threads).

How can I use Flask inside class?


Solution

  • Although this works it doesn't feel compliant with the Flask style guide. If you need to wrap a Flask application inside your project, create a separate class to your needs and add functions that should be executed

    from flask import Flask, Response
    
    
    class EndpointAction(object):
    
        def __init__(self, action):
            self.action = action
            self.response = Response(status=200, headers={})
    
        def __call__(self, *args):
            self.action()
            return self.response
    
    
    class FlaskAppWrapper(object):
        app = None
    
        def __init__(self, name):
            self.app = Flask(name)
    
        def run(self):
            self.app.run()
    
        def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None):
            self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler))
    
    
    def action():
        # Execute anything
    
    a = FlaskAppWrapper('wrap')
    a.add_endpoint(endpoint='/ad', endpoint_name='ad', handler=action)
    a.run()
    

    Some things to note here:

    • EndpointAction is supposed to be a wrapper that will execute your function and generate an empty 200 response. If you want you can edit the functionality
    • The endpoint handler can be anything that has a __call__ method defined
    • The endpoint name should be unique as it represents a view name
    • Adding endpoints after the application is not possible as the thread will block once the application starts. You can enable it by running the application on a separate thread but changing the URL map on the fly is not advised, neither thread safe