Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a decorator function defined as an instance variable

(Although this question is specifically about Flask, it can be generalised as per the title)

I'm trying to use Flask's app.route() decorator inside a class. However, the Flask app is initialised as an instance variable, i.e. self.server is set to the app. This means that I can't use the decorator, as self is undefined outside of the decorated method. I would like to be able to do the following:

class MyClass:

    def __init__(self):
        self.server = Flask(__name__)

    @self.server.route('/')
    def home():
        return '<h1>Success</h1>'

Are there any work-arounds for this issue? Any help is greatly appreciated!

like image 976
Cadel Watson Avatar asked Dec 22 '16 05:12

Cadel Watson


2 Answers

You can define the function in the context of the __init__ method. Then, to make the function able to be called normally, set the home member equal to it.

class MyClass:
    def __init__(self):
        self.server = Flask(__name__)

        # This is indented at __init__'s level, so a new instance of the function
        # is defined every time __init__ runs. That means a new instance
        # is defined for each instance of the class, and so it can be wrapped with
        # the instance's "self" value.
        @self.server.route('/')
        def home_func():
            return '<h1>Success</h1>'

        # Then, you make it an object member manually:
        self.home = home_func
like image 58
IanPudney Avatar answered Nov 15 '22 10:11

IanPudney


Instead of using the route() decorator, you should use the add_url_rule method of the self.server object, like so:

class MyClass:
    def __init__(self):
        self.server = Flask(__name__)
        self.server.add_url_rule('/', 'home', self.home)
        self.server.add_url_rule('/route-1', 'route-1', self.route_1)
        self.server.add_url_rule('/route-2', 'route-2', self.route_2)

    def home():
        return '<h1>Success</h1>'

    def route_1():
        ...

    def route_2():
        ...

This pattern allows you to define your route handlers as methods on the class and is much easier to read, as you can see all of your URL rules in one block.

like image 29
YellowShark Avatar answered Nov 15 '22 09:11

YellowShark