Flask 擴(kuò)展的代碼

2021-08-11 21:18 更新

下面是用來(lái)復(fù)制/粘貼的 flask_sqlite3.py 的內(nèi)容:

import sqlite3
from flask import current_app

# Find the stack on which we want to store the database connection.
# Starting with Flask 0.9, the _app_ctx_stack is the correct one,
# before that we need to use the _request_ctx_stack.
try:
    from flask import _app_ctx_stack as stack
except ImportError:
    from flask import _request_ctx_stack as stack


class SQLite3(object):

    def __init__(self, app=None):
        self.app = app
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.config.setdefault('SQLITE3_DATABASE', ':memory:')
        # Use the newstyle teardown_appcontext if it's available,
        # otherwise fall back to the request context
        if hasattr(app, 'teardown_appcontext'):
            app.teardown_appcontext(self.teardown)
        else:
            app.teardown_request(self.teardown)

    def connect(self):
        return sqlite3.connect(current_app.config['SQLITE3_DATABASE'])

    def teardown(self, exception):
        ctx = stack.top
        if hasattr(ctx, 'sqlite3_db'):
            ctx.sqlite3_db.close()

    @property
    def connection(self):
        ctx = stack.top
        if ctx is not None:
            if not hasattr(ctx, 'sqlite3_db'):
                ctx.sqlite3_db = self.connect()
            return ctx.sqlite3_db

那么這是這些代碼做的事情:

  1. __init__ 方法接受一個(gè)可選的應(yīng)用對(duì)象,并且如果提供,會(huì)調(diào)用 init_app 。

  2. init_app 方法使得 SQLite3 對(duì)象不需要應(yīng)用對(duì)象就可以實(shí)例化。這個(gè)方法 支持工廠模式來(lái)創(chuàng)建應(yīng)用。 init_app 會(huì)為數(shù)據(jù)庫(kù)設(shè)定配置,如果不提供配置,默 認(rèn)是一個(gè)內(nèi)存中的數(shù)據(jù)庫(kù)。此外, init_app 方法附加了 teardown 處理器。 它會(huì)試圖使用新樣式的應(yīng)用上下文處理器,并且如果它不存在,退回到請(qǐng)求上下文處理 器。

  3. 接下來(lái),我們定義了 connect 方法來(lái)打開(kāi)一個(gè)數(shù)據(jù)庫(kù)連接。

  4. 最后,我們添加一個(gè) connection 屬性,首次訪問(wèn)時(shí)打開(kāi)數(shù)據(jù)庫(kù)連接,并把它存儲(chǔ) 在上下文。這也是處理資源的推薦方式:在資源第一次使用時(shí)惰性獲取資源。

    注意這里,我們把數(shù)據(jù)庫(kù)連接通過(guò) _app_ctx_stack.top 附加到應(yīng)用上下文 的棧頂。擴(kuò)展應(yīng)該使用上下文的棧頂來(lái)存儲(chǔ)它們自己的信息,并使用足夠復(fù)雜的 名稱。注意如果應(yīng)用使用不支持它的老版本的 Flask 我們退回到 _request_ctx_stack.top 。

那么為什么我們決定在此使用基于類的方法?因?yàn)槭褂梦覀兊臄U(kuò)展的情況看起來(lái) 會(huì)是這樣:

from flask import Flask
from flask_sqlite3 import SQLite3

app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
db = SQLite3(app)

你之后可以在視圖中這樣使用數(shù)據(jù)庫(kù):

@app.route('/')
def show_all():
    cur = db.connection.cursor()
    cur.execute(...)

同樣地,如果你在請(qǐng)求之外,而你在使用支持應(yīng)用上下文 Flask 0.9 或之后的版本, 你可以用同樣的方法使用數(shù)據(jù)庫(kù):

with app.app_context():
    cur = db.connection.cursor()
    cur.execute(...)

with 塊的最后,銷毀處理器會(huì)自動(dòng)執(zhí)行。

此外, init_app 方法用于支持創(chuàng)建應(yīng)用的工廠模式:

db = Sqlite3()
# Then later on.
app = create_app('the-config.cfg')
db.init_app(app)

記住已審核的 Flask 擴(kuò)展需要支持用工廠模式來(lái)創(chuàng)建應(yīng)用(下面會(huì)解釋)。

init_app 的注意事項(xiàng)

如你所見(jiàn), init_app 不分配 appself 。這是故意的!基于 類的 Flask 擴(kuò)展必須只在應(yīng)用傳遞到構(gòu)造函數(shù)時(shí)在對(duì)象上存儲(chǔ)應(yīng)用。這告訴擴(kuò) 展:我對(duì)使用多個(gè)應(yīng)用沒(méi)有興趣。

當(dāng)擴(kuò)展需要找出當(dāng)前的應(yīng)用且它沒(méi)有一個(gè)指向其的引用時(shí),必須使用 current_app 上下文局域變量或用一種你可以顯式傳遞應(yīng)用的 方法更改 API 。


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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)