How to pass class's self through a flask.Blueprint.route decorator?

Question:

I am writing my website’s backend using Flask and Python 2.7, and have run into a bit of a problem. I like to use classes to enclose my functions, it makes things neat for me and helps me keep everything modular. One problem I’m having, though, is that the decorators flask uses for routing doesn’t preserve the self variable. I use this for accessing the loadDb method of the class that its in. See below. Anyone have any ideas why this is happening, and know how I could solve this, or even if there is a way to solve this?

class Test(object):
    blueprint = Blueprint("Test", __name__)
    def __init__(self, db_host, db_port):
        self.db_host = db_host
        self.db_port = db_port
    def loadDb(self):
        return Connection(self.db_host, self.db_port)
    @blueprint.route("/<var>")
    def testView(var): # adding self here gives me an error
        return render_template("base.html", myvar=self.loadDb().find({"id": var})
Asked By: Smartboy

||

Answers:

There is an error if you add self because the method works the same as a function for the decorator, and the flask isn’t expecting a function with a first argument self.

Let’s look at the code of route : https://github.com/pallets/flask/blob/master/src/flask/blueprints.py#L52

It calls self.add_url_rule (self being the Blueprint) with a few arguments, one of those being the function. What you want is to add a rule with the method bound to an instance of Test(self.testView), not the method itself (Test.testview). This is tricky because the decorator is executed at the creation of the class, before any instance ever exist.

The solution I can suggest, asside from avoiding to put your views as methods of a class, is to call yourself blueprint.add_url_rule in the contructor of Test (i.e., at the first point the instance of Test is known.

Answered By: madjar
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.