2017-10-21 266 views
1

我有一個項目,我定義我的db.py模塊:Python的SQLAlchemy的燒瓶模式

app = get_global_flask_app() 
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql://foo:[email protected]:5432/test" 
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False 
db = SQLAlchemy(app) 
db.create_all() 

然後我導入db.db到需要查詢數據庫和插入數據(DB模塊。 session.query())。

但是,這意味着當我編寫測試代碼(pytest)來測試任何導入db.py的模塊時,我需要定義「SQLALCHEMY_DATABASE_URI」。一種解決方案是讓db是一個懶惰屬性,以便上面的代碼僅在數據庫被使用/測試時纔在測試中執行。是否有Flask()+ SQLA + SQLALCHEMY_DATABASE_URI在那裏我缺少的常見設計模式?你會如何解決這個問題?燒瓶配置?

回答

1

我們通常解決這個問題的方法是使用application factory和一個配置。

這意味着你在你的項目中,看起來像這樣(從文件經修改後服用)有一個函數的地方:

def create_app(config_filename, settings_override=None): 
    app = Flask(__name__) 
    app.config.from_pyfile(config_filename) 
    app.config.from_object(settings_override) 

    from yourapplication.model import db 
    db.init_app(app) 

    from yourapplication.views.admin import admin 
    from yourapplication.views.frontend import frontend 
    app.register_blueprint(admin) 
    app.register_blueprint(frontend) 

    return app 

然後(希望你使用pytest)在根目錄下的測試,你有一個conftest文件,自動準備測試環境是這樣的:

import pytest 
from your_project import create_app 


class TestConfig: 
    SQLALCHEMY_DATABASE_URI = "postgresql://foo:[email protected]:5432/test" 
    SQLALCHEMY_TRACK_MODIFICATIONS = False 
    ANY OTHER SETTINGS... 


@pytest.fixture(autouse=True) 
def app(request): 
    app = create_app(settings_override=TestConfig) 
    ctx = app.app_context() 
    ctx.push() 

    def teardown(): 
     ctx.pop() 

    request.addfinalizer(teardown) 

    return app 

通常情況下,我們創建另一個夾具這也是autouse=True,處理該數據庫的建立,沖洗和可能需要加載燈具,並且只能在需要訪問數據庫的測試中使用該燈具(集成或功能測試),這意味着我們只包含在與我們的集成測試相同的目錄中的conftest文件中。