Bottle 框架和 OOP,使用方法而不是函数
Posted
技术标签:
【中文标题】Bottle 框架和 OOP,使用方法而不是函数【英文标题】:Bottle framework and OOP, using method instead of function 【发布时间】:2012-02-02 06:43:13 【问题描述】:我已经用 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 中使用方法而不是函数?
【问题讨论】:
为什么不装瓶CBV github.com/techchunks/bottleCBV 【参考方案1】:您的代码不起作用,因为您试图路由到非绑定方法。非绑定方法没有对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
【讨论】:
请注意bottle.route(attr.route, attr)
不会按预期工作;你想要bottle.route(attr.route)(attr)
(因为bottle.route() 是一个装饰器,它返回一个可调用对象,然后消耗(attr)
)。
感谢您的来信!修好了。
您好,我只是建议将其集成到bottle
,请参阅issue 1224。我会对那里的 cmets 感到满意。 :)【参考方案2】:
下面对我来说很好用:) 非常面向对象且易于理解。
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()
【讨论】:
嗨,-1:这个解决方案不是面向对象的,它包装了类中模块中的代码,加上将它与服务器功能混合。跨度> 这个解决方案使用组合而不是继承,这在 OOP 中非常好。引用 wikipedia 上的内容:支持组合而不是继承是一种设计原则,它赋予设计更高的灵活性。我【参考方案3】:您必须扩展 Bottle
类。它的实例是 WSGI Web 应用程序。
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)
大多数示例正在做的事情,包括之前为这个问题提供的答案,都是重用“默认应用程序”,而不是创建自己的应用程序,也没有使用面向对象和继承的便利。
【讨论】:
如果你有几十条路线怎么办? @Alex-Bogdanov 您必须以一种或另一种方式定义您的路线。你可以在你的路由中使用通配符,它允许你调用一个方法并根据你使用的路由给它一个参数。这允许您拥有比实际可能的路线更少的路线定义。 这个答案帮助我实现了基于类的定义 :) 有关信息,也可以直接使用self.error(error_code, callback=method)
和最新的 bottle
代码或使用 self.error(error_code)(method)
和 @ 来“路由”错误987654328@.
@Joël 你在做什么对我来说听起来恰到好处。你并没有真正规避任何东西,而是实现了一些缺失的东西。如果您检查标签并在构造函数中添加路由,它看起来会很干净。事实上,子类 Bottle 只是为了做到这一点,然后使用你的新类作为基类,你就再也不用看到路由代码了!
这正是它最终的样子!所以,因为这实际上是非常精简的东西,我创建了an issue on bottle bugtracker 来提出一个贡献:)【参考方案4】:
我接受了@Skirmantas 的回答并对其进行了一些修改,以允许在装饰器中使用关键字参数,例如方法、跳过等:
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)
【讨论】:
【参考方案5】:试试这个,对我有用,文档也很不错,可以开始使用...
https://github.com/techchunks/bottleCBV
【讨论】:
以上是关于Bottle 框架和 OOP,使用方法而不是函数的主要内容,如果未能解决你的问题,请参考以下文章
让python bottle框架支持jquery ajax的RESTful风格的PUT和DELETE等请求