使用定义为实例变量的装饰器函数

Using a decorator function defined as an instance variable

(虽然这个问题是专门针对Flask的,但可以按照标题概括)

我正在尝试在 class 中使用 Flask 的 app.route() 装饰器。但是,Flask 应用程序被初始化为一个实例变量,即 self.server 被设置为应用程序。这意味着我不能使用装饰器,因为 self 在装饰方法之外是未定义的。我希望能够做到以下几点:

class MyClass:

    def __init__(self):
        self.server = Flask(__name__)

    @self.server.route('/')
    def home():
        return '<h1>Success</h1>'

这个问题有 work-arounds 吗?非常感谢任何帮助!

您可以在 __init__ 方法的上下文中定义函数。然后,为了使函数能够正常调用,设置home成员等于它。

class MyClass:
    def __init__(self):
        self.server = Flask(__name__)

        # This is indented at __init__'s level, so a new instance of the function
        # is defined every time __init__ runs. That means a new instance
        # is defined for each instance of the class, and so it can be wrapped with
        # the instance's "self" value.
        @self.server.route('/')
        def home_func():
            return '<h1>Success</h1>'

        # Then, you make it an object member manually:
        self.home = home_func

我不确定您的总体用例是什么,但不将应用程序对象嵌入 class 而是使用 Flask 的 Pluggable Views 模块可能会更好。这将允许您将视图清晰地定义为继承自 flask.views.View 的 classes。示例:

import flask
import flask.views

class MyClass(flask.views.View):
  def dispatch_request(self):
    return '<h1>Success</h1>'

app.add_url_rule('/test', view_func=MyClass.as_view('home'))

鉴于这个小例子,这肯定是更多的代码,但这使您可以更灵活地定义其他 classes 或具有自己路由的函数,并且可能考虑使用 MethodViews,它为定义多个 HTTP 方法并将它们与单个 class.

相关联

您应该使用 self.server 对象的 add_url_rule method 而不是使用 route() 装饰器,如下所示:

class MyClass:
    def __init__(self):
        self.server = Flask(__name__)
        self.server.add_url_rule('/', 'home', self.home)
        self.server.add_url_rule('/route-1', 'route-1', self.route_1)
        self.server.add_url_rule('/route-2', 'route-2', self.route_2)

    def home():
        return '<h1>Success</h1>'

    def route_1():
        ...

    def route_2():
        ...

此模式允许您将路由处理程序定义为 class 上的方法,并且更易于阅读,因为您可以在一个块中看到所有 URL 规则。