Bottle框架与面向对象编程,使用方法替代函数

40 投票
6 回答
15386 浏览
提问于 2025-04-17 09:31

我用Bottle做了一些编程。它非常简单,正好满足我的需求。不过,当我尝试把应用程序封装成一个类的时候,我遇到了一些困难:

import bottle
app = bottle

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

    # Doesn't work
    @app.route("/1")
    def index1(self):
        return("I'm 1 | self.param = %s" % self.param)

    # Doesn't work
    @app.route("/2")
    def index2(self):
        return("I'm 2")

    # Works fine
    @app.route("/3")
    def index3():
        return("I'm 3")

在Bottle中可以用方法代替函数吗?

6 个回答

29

下面的代码对我来说很好用 :)
它很面向对象,容易理解。

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()
30

你需要扩展一下 Bottle 这个类。它的实例就是 WSGI 网络应用。

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)

大多数网上的例子,包括之前对这个问题的回答,都是在重复使用“默认应用”,而不是创建自己的应用,也没有利用面向对象和继承的便利。

42

你的代码之所以不工作,是因为你试图访问那些没有绑定的方法。没有绑定的方法是指它们没有指向 self 的引用。如果没有创建 App 的实例,它们怎么能有呢?

如果你想访问类的方法,首先得初始化你的类,然后用 bottle.route() 来指向那个对象上的方法,像这样:

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)

如果你想把路由定义放在处理函数附近,可以这样做:

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)

不要在 App.__init__() 里做 bottle.route() 的部分,因为那样你就无法创建两个 App 类的实例了。

如果你更喜欢装饰器的语法,而不是设置属性 index.route=,你可以写一个简单的装饰器:

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

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

撰写回答