Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bottle framework and OOP, using method instead of function

Your code does not work because you are trying to route to non-bound methods. Non-bound methods do not have a reference to self, how could they, if instance of App has not been created?

If you want to route to class methods, you first have to initialize your class and then bottle.route() to methods on that object like so:

import bottle        

class App(object):
    def __init__(self,param):
        self.param   = param

    def index1(self):
        return("I'm 1 | self.param = %s" % self.param)

myapp = App(param='some param')
bottle.route("/1")(myapp.index1)

If you want to stick routes definitions near the handlers, you can do something like this:

def routeapp(obj):
    for kw in dir(app):
        attr = getattr(app, kw)
        if hasattr(attr, 'route'):
            bottle.route(attr.route)(attr)

class App(object):
    def __init__(self, config):
        self.config = config

    def index(self):
        pass
    index.route = '/index/'

app = App({'config':1})
routeapp(app)

Don't do the bottle.route() part in App.__init__(), because you won't be able to create two instances of App class.

If you like the syntax of decorators more than setting attribute index.route=, you can write a simple decorator:

def methodroute(route):
    def decorator(f):
        f.route = route
        return f
    return decorator

class App(object):
    @methodroute('/index/')
    def index(self):
        pass

Below works nicely for me :) Quite object orientated and easy to follow.

from bottle import Bottle, template

class Server:
    def __init__(self, host, port):
        self._host = host
        self._port = port
        self._app = Bottle()
        self._route()

    def _route(self):
        self._app.route('/', method="GET", callback=self._index)
        self._app.route('/hello/<name>', callback=self._hello)

    def start(self):
        self._app.run(host=self._host, port=self._port)

    def _index(self):
        return 'Welcome'

    def _hello(self, name="Guest"):
        return template('Hello {{name}}, how are you?', name=name)

server = Server(host='localhost', port=8090)
server.start()

You have to extend the Bottle class. It's instances are WSGI web applications.

from bottle import Bottle

class MyApp(Bottle):
    def __init__(self, name):
        super(MyApp, self).__init__()
        self.name = name
        self.route('/', callback=self.index)

    def index(self):
        return "Hello, my name is " + self.name

app = MyApp('OOBottle')
app.run(host='localhost', port=8080)

What most examples out there are doing, including the answers previously provided to this question, are all reusing the "default app", not creating their own, and not using the convenience of object orientation and inheritance.


I took @Skirmantas answer and modified it a bit to allow for keyword arguments in the decorator, like method, skip, etc:

def routemethod(route, **kwargs):
    def decorator(f):
        f.route = route
        for arg in kwargs:
            setattr(f, arg, kwargs[arg])
        return f
    return decorator

def routeapp(obj):
    for kw in dir(obj):
        attr = getattr(obj, kw)
        if hasattr(attr, "route"):
            if hasattr(attr, "method"):
                method = getattr(attr, "method")
            else:
                method = "GET"
            if hasattr(attr, "callback"):
                callback = getattr(attr, "callback")
            else:
                callback = None
            if hasattr(attr, "name"):
                name = getattr(attr, "name")
            else:
                name = None
            if hasattr(attr, "apply"):
                aply = getattr(attr, "apply")
            else:
                aply = None
            if hasattr(attr, "skip"):
                skip = getattr(attr, "skip")
            else:
                skip = None

            bottle.route(attr.route, method, callback, name, aply, skip)(attr)

try this, worked for me, documentation is also pretty decent to get started with ...

https://github.com/techchunks/bottleCBV