[Python] 在 Bottle Web Framework 中以类的方式创建应用

  在 Bottle 框架中,使用 route 修饰符将请求路由到与之对应的响应方法。这种特性非常适合路由请求与方法,但却给在 Bottle 中使用类来创建应用带了麻烦。

 class SanYou:
  
      app = Bottle()
  
      @app.route('/')
      def homepage(self):
          return "Welcome!"
  
 app1 = SanYou().app
 app2 = SanYou.app

  

  以上代码中无论是 app1 还是 app2,均返回 TypeError: homepage() takes exactly 1 argument (0 given)

  这是因为在以上代码中 homepage 没有绑定到 SanYou 实例,即作为路由方法的修饰符,提前封装了实例方法 homepage ,造成 self 不能传入 homepage 方法中,于是 homepage 与 SanYou 实例没有绑定。

 class SanYou:
  
      app = Bottle()
  
      @classmethod
      @app.route('/')
      def homepage(cls):
          return "Welcome!"
  
 app = SanYou.app

  

  同理,以上代码中由于路由修饰符会封装类方法,造成 cls 无法传入 homepage 方法中,造成 homepage 不能成为类方法。注意,改变修饰符顺序也无法使得两个修饰符进行正确封装。

class SanYou:

    app = Bottle()

    @app.route('/')
    @classmethod
    def homepage(cls):
        return "Welcome!"

app = SanYou.app

  

  执行以上代码,你会得到 “TypeError: 'classmethod' object is not callable”。

  因此,若想在类中使用修饰符进行路由,那只能使用静态方法,如:

# code 1
class SanYou:

    app = Bottle()

    @staticmethod
    @app.route('/')
    def homepage():
        return "Welcome!"

app = SanYou.app
----------------------------------------------
# code 2
class SanYou:

    app = Bottle()

    @app.route('/')
    def homepage():
        return "Welcome!"

app = SanYou.app

  

  以上两种写法都会正确创建 app ,第一种是规范的静态方法写法。如果想要在 bottle 中使用类来创建应用,同时使用修饰符进行路由,在不重写修饰符的前提下,创建一个全部都是静态方法的类才能满足要求。

 

  如果你不是偏执于修饰符的路由方式,那么就让我们来使用一个看上去更加正常的类来创建应用吧。

  在 bottle 中,修饰符路由是它一个特性,但是修饰符本身就是一种语法糖而已,因此让我们暂时放弃这种语法糖,直接使用 route 方法来进行路由。

class SanYou:

    def homepage(self):
        return "Welcome!"

sanYou = SanYou()
app = Bottle()
app.route('/')(sanYou.homepage)

"""
bottle中使用route的两种写法

写法一:
@app.route(url)
function()

写法二:
app.route(url)(function)

写法一等同写法二。
"""

 

  在以上代码中,首先将 SanYou 实例化,得到一个 sanYou 实例,然后创建 app,并在这个应用中,将来自 url="/" 的请求路由到 sanYou 的实例方法 homepage 处理。因此,当随着路由地址增加,不妨如下编码以便集中管理路由。

class SanYou:

    def homepage(self):
        return "Welcome!"

    def service(self):
        return "Hello!"


def appRoute(app):
    sanYou = SanYou()

    routeDict = {
        '/': sanYou.homepage,
        '/home': sanYou.homepage,
        '/service': sanYou.service,
    }

    for url in routeDict:
        app.route(url)(routeDict[url])

app = Bottle()
appRoute(app)

 

  在 appRoute 函数的 routeDict 中,可以很方便地集中配置路由。这种写法是不是让 bottle 看上去不像 bottle ,反而更像是 Django 或 webapp.py 等呢?

 

posted @ 2013-04-12 03:21  iFantasticMe  阅读(711)  评论(0编辑  收藏  举报