Flask 延遲加載視圖

2021-08-11 10:32 更新

Flask 通常配合裝飾器使用,裝飾器使用非常簡(jiǎn)單,而且使您可以將 URL 和處理它的函數(shù) 放在一起。然而這種方法也有一種不足: 這就意味著您使用裝飾器的代碼必須在前面導(dǎo)入, 否則 Flask 將無(wú)法找到您的函數(shù)。

這對(duì)于需要很快導(dǎo)入的應(yīng)用程序來(lái)說(shuō)是一個(gè)問(wèn)題,這種情況可能出現(xiàn)在類(lèi)似谷歌的 App Engine 這樣的系統(tǒng)上。所以如果您突然發(fā)現(xiàn)您的引用超出了這種方法可以處理 的能力,您可以降級(jí)到中央 URL 映射的方法。

用于激活中央 URL 映射的函數(shù)是 add_url_rule() 方法。 您需要提供一個(gè)設(shè)置應(yīng)用程序所有 URL 的文件,而不是使用裝飾器。

轉(zhuǎn)換到中央 URL 映射

假象現(xiàn)在的應(yīng)用的樣子如下所示:

from flask import Flask
app = Flask(__name__)

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

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

而中央 URL 映射的方法下,您需要一個(gè)不包含任何裝飾器的文件(views.py), 如下所示:

def index():
    pass

def user(username):
    pass

然后使用一個(gè)文件初始化應(yīng)用并將函數(shù)映射到 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)

延遲加載

目前我們僅僅將視圖和路徑配置分開(kāi)了,但是模塊仍然是在前面導(dǎo)入的。下面的技巧 使得視圖函數(shù)可以按需加載??梢允褂靡粋€(gè)輔助類(lèi)來(lái)實(shí)現(xiàn),這個(gè)輔助類(lèi)以函數(shù)的方式 作用,但是當(dāng)?shù)谝淮问褂媚硞€(gè)函數(shù)時(shí),它才在內(nèi)部導(dǎo)入這個(gè)函數(shù):

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)

在使用這種方法時(shí),將 __module____name__ 變量設(shè)定為合適的值是很重要的。 在你沒(méi)有手動(dòng)指定一個(gè) URL 規(guī)則時(shí),這兩個(gè)變量被 Flask 用于在內(nèi)部確定如何命名 URL 規(guī)則。

現(xiàn)在您就可以定義您將視圖整合到的位置,如下所示:

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'))

您可以進(jìn)一步改進(jìn)它,以便于節(jié)省鍵盤(pán)敲擊次數(shù)。通過(guò)編寫(xiě)一個(gè)在內(nèi)部調(diào)用 add_url_rule() 方法的函數(shù),自動(dòng)將一個(gè)包含項(xiàng)目名稱(chēng) 以及點(diǎn)符號(hào)的字符串添加為前綴,并按需將 view_func 封裝進(jìn) LazyView

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

url('/', 'views.index')
url('/user/<username>', 'views.user')

需要記住的是,請(qǐng)求前后激發(fā)的回調(diào)處理器必須在一個(gè)文件里,并在前面導(dǎo)入, 使之在第一個(gè)請(qǐng)求到來(lái)之間能夠合適地工作。對(duì)于其他所有的裝飾器來(lái)說(shuō)也是 一樣的。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)