延迟加载视图

Flask通常与装饰器一起使用。 Flask 通常配合装饰器使用,装饰器使用非常简单,而且使您可以将 URL 和处理它的函数 放在一起。 然而这种方法也有一种不足: 这就意味着您使用装饰器的代码必须在前面导入, 否则 Flask 将无法找到您的函数。

如果您的应用程序必须快速导入,这可能是一个问题。它可能必须在Google的App Engine或其他系统等系统上执行。 所以如果您突然发现您的引用超出了这种方法可以处理 的能力,您可以降级到中央 URL 映射的方法。

用于激活中央 URL 映射的函数是 add_url_rule() 方法。 您需要提供一个设置应用程序所有 URL 的文件,而不是使用装饰器。

转换为集中式URL地图

想象当前的应用程序看起来有点像这样:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    pass

@app.route('/user/<username>')
def user(username):
    pass

然后,使用集中式方法,您将有一个文件包含视图(views.py),但没有任何装饰器:

def index():
    pass

def user(username):
    pass

然后使用一个文件初始化应用并将函数映射到 URLs:

from flask import Flask
from yourapplication import views
app = Flask(__name__)
app.add_url_rule('/', view_func=views.index)
app.add_url_rule('/user/<username>', view_func=views.user)

加载晚

目前我们仅仅将视图和路径配置分开了,但是模块仍然是在前面导入的。 下面的技巧 使得视图函数可以按需加载。 这可以通过一个辅助类实现,它的行为就像一个函数,但内部导入真正的函数首次使用:

from werkzeug import import_string, cached_property

class LazyView(object):

    def __init__(self, import_name):
        self.__module__, self.__name__ = import_name.rsplit('.', 1)
        self.import_name = import_name

    @cached_property
    def view(self):
        return import_string(self.import_name)

    def __call__(self, *args, **kwargs):
        return self.view(*args, **kwargs)

在使用这种方法时,将 __module____name__ 变量设定为合适的值是很重要的。 在你没有手动指定一个 URL 规则时,这两个变量被 Flask 用于在内部确定如何命名 URL 规则。

现在您就可以定义您将视图整合到的位置,如下所示:

from flask import Flask
from yourapplication.helpers import LazyView
app = Flask(__name__)
app.add_url_rule('/',
                 view_func=LazyView('yourapplication.views.index'))
app.add_url_rule('/user/<username>',
                 view_func=LazyView('yourapplication.views.user'))

您可以通过使用一个函数来调用add_url_rule(),通过为项目名称和点添加字符串,然后通过包装来进一步优化这种写入操作所需的击键数量。 view_funcLazyView中。

def url(import_name, url_rules=[], **options):
    view = LazyView('yourapplication.' + import_name)
    for url_rule in url_rules:
        app.add_url_rule(url_rule, view_func=view, **options)

# add a single route to the index view
url('views.index', ['/'])

# add two routes to a single function endpoint
url_rules = ['/user/','/user/<username>']
url('views.user', url_rules)

需要记住的是,请求前后激发的回调处理器必须在一个文件里,并在前面导入, 使之在第一个请求到来之间能够合适地工作。 对于其他所有的装饰器来说也是 一样的。