2013-10-17 61 views
53

我通過散佈模型,藍圖來重新分解我的燒瓶應用程序,但我遇到運行時錯誤。當散射燒瓶模型時,RuntimeError:'未在db上註冊的應用程序'被提出

def create_app(): 
    app = flask.Flask("app") 
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' 
    app.register_blueprint(api) 
    db.init_app(app) 
    db.create_all() 
    return app 

我有以下問題(示例項目在這裏舉行:https://github.com/chfw/sample):

Traceback (most recent call last): 
    File "application.py", line 17, in <module> 
    app = create_app() 
    File "application.py", line 12, in create_app 
    db.create_all() 
    File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 856, in create_all 
    self._execute_for_all_tables(app, bind, 'create_all') 
    File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 836, in _execute_for_all_tables 
    app = self.get_app(app) 
    File "\AppData\Roaming\Python\Python27\site-packages\flask_sqlalchemy\__init__.py", line 809, in get_app 
    raise RuntimeError('application not registered on db 
      'RuntimeError: application not registered on db 
      instance and no application bound to current context 

我做了這個主題的研究。再保在這裏建議:

Flask-SQLAlchemy import/context issue

同樣的問題在這裏提出:

http://flask.pocoo.org/mailinglist/archive/2010/8/30/sqlalchemy-init-app-problem/#b1c3beb68573efef4d6e571ebc68fa0b

和上面的線(2010)提出這樣一個黑客:

app.register_blueprint(api) 
    db.app=app #<------------<< 
    db.init_app(app) 

有沒有人知道如何正確地做到這一點?你是如何解決它的?

感謝

回答

121

這與瓶的application context做。當使用db.init_app(app)進行初始化時,Flask-SQLAlchemy不知道哪個應用程序是「當前」應用程序(請記住,Flask允許在同一個解釋器中使用multiple apps)。你可能有多個應用在同一個進程中使用相同的SQLAlchemy實例,並且Flask-SQLAlchemy需要知道哪個是「當前」實例(由於Flask的所有特性都是context local)。

如果您需要在運行時執行此操作,則必須明確說出哪個應用程序是所有調用的「當前」應用程序。你可以通過改變你的代碼這樣做是爲了使用with app.app_context()塊:

def create_app(): 
    app = flask.Flask("app") 
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' 
    app.register_blueprint(api) 
    db.init_app(app) 
    with app.app_context(): 
     # Extensions like Flask-SQLAlchemy now know what the "current" app 
     # is while within this block. Therefore, you can now run........ 
     db.create_all() 

    return app 

如果您正在編寫需要的應用程序上下文獨立的腳本,你可以在開始,而不是把一切推入上下文一個with塊。

create_app().app_context().push() 

如果你寫瓶的cli命令該命令將自動訪問上下文。

+0

對,這是有效的。現在我沒有得到例外。但接下來是:「應用程序未註冊數據庫」 - > RuntimeError:應用程序未註冊數據庫實例,沒有應用程序綁定到當前上下文 – chfw

+2

這裏的區別和添加db.app =應用程序? – user805981

+1

@ user805981這種方式可能有效,但不是很乾淨。首先,你打破封裝,因爲SQLAlchemy上的'app'屬性並不是公開的。當它改變正在使用的應用程序時,該對象可能需要做其他事情。其次,'app_context'不僅僅是改變Flask-SQLAlchemy;它實際上告訴Flask更改當前的應用程序。因此,您可能需要使用各種Flask API來處理這些事情,或者與您的其他Flask擴展一起使用該應用程序。 –

5

馬克的回答非常好,它對我有很大的幫助。然而,解決這個問題的另一種方法是運行依賴於應用上下文的代碼,該函數用@ app.before_first_request修飾。有關更多信息,請參閱http://flask.pocoo.org/docs/0.10/appcontext/。實際上,我最終這麼做了,主要是因爲我想能夠在燒瓶外部調用初始化代碼,這也是我以這種方式處理的。

對我而言,我希望能夠在沒有Flask-SQLAlchemy的情況下將SQLAlchemy模型作爲普通的SQLAlchemy模型進行測試,但下面的代碼中的數據庫只是一個(Flask)SQLAlchemy數據庫。

@app.before_first_request 
def recreate_test_databases(engine = None, session = None): 
    if engine == None: 
    engine = db.engine 
    if session == None: 
    session = db.session 

    Base.metadata.drop_all(bind=engine) 
    Base.metadata.create_all(bind=engine) 
    # Additional setup code 
+0

約翰,你可以合併重複的答案到這一個(因爲這一個upvotes),並刪除其他? – KobeJohn

+0

已刪除,無需合併。 –

+0

對應該保存'@ app.before_first_request'函數的文件的任何建議? – AlexLordThorsen

相關問題