Using flask inside class

So I just came across the library Flask-Classful

which was really simple comparatively

To create a simple web app inside a class is this:

from flask import Flask
from flask_classful import FlaskView

app = Flask(__name__)

class TestView(FlaskView):

    def index(self):
    # http://localhost:5000/
        return "<h1>This is my indexpage</h1>"

TestView.register(app,route_base = '/')

if __name__ == '__main__':
    app.run(debug=True) 

Handling multiple route and dynamic route is also simple

class TestView(FlaskView):

    def index(self):
    # http://localhost:5000/
        return "<h1>This is my indexpage</h1>"

    def secondpage(self):
    # http://localhost:5000/secondpage
        return "<h1>This is my second</h1>"
    
    def thirdpage(self,name):
    # dynamic route
    # http://localhost:5000/thirdpage/sometext
        return "<h1>This is my third page <br> welcome"+name+"</h1>"

TestView.register(app,route_base = '/')

Adding own route name with a different method that is also possible

from flask_classful import FlaskView,route

class TestView(FlaskView):

    def index(self):
    # http://localhost:5000/
        return "<h1>This is my indexpage</h1>"


    @route('/diffrentname')
    def bsicname(self):
    # customized route
    # http://localhost:5000/diffrentname
        return "<h1>This is my custom route</h1>"
TestView.register(app,route_base = '/')

This gives the potential to create separate class and handlers for a separate dependent and independent process and just import them as a package to run on the main file or wrapper file

from package import Classname
Classname.register(app,route_base = '/')

which is really simple and object-oriented


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

To complete Kostas Pelelis's answer, because I had some difficulty to find the why the Response wasn't directly using the Action returned value.

Here is another version of FLASK class without decorators :

class EndpointAction(object):

    def __init__(self, action):
        self.action = action

    def __call__(self, *args):
        # Perform the action
        answer = self.action()
        # Create the answer (bundle it in a correctly formatted HTTP answer)
        self.response = flask.Response(answer, status=200, headers={})
        # Send it
        return self.response

class FlaskAppWrapper(object):

    def add_all_endpoints(self):
        # Add root endpoint
        self.add_endpoint(endpoint="/", endpoint_name="/", handler=self.action)

        # Add action endpoints
        self.add_endpoint(endpoint="/add_X", endpoint_name="/add_X", handler=self.add_X)
        # you can add more ... 

    def add_endpoint(self, endpoint=None, endpoint_name=None, handler=None):
        self.app.add_url_rule(endpoint, endpoint_name, EndpointAction(handler)) 
        # You can also add options here : "... , methods=['POST'], ... "

    # ==================== ------ API Calls ------- ====================
    def action(self):
        # Dummy action
        return "action" # String that will be returned and display on the webpage
        # Test it with curl 127.0.0.1:5000

    def add_X(self):
        # Dummy action
        return "add_X"
        # Test it with curl 127.0.0.1:5000/add_X

Tags:

Python

Flask