Python 散布 Flask 模型时,会引发 RuntimeError: 'application not register on db'
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19437883/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When scattering Flask Models, RuntimeError: 'application not registered on db' was raised
提问by chfw
I am re-factoring my Flask application by scattering the models, blueprints but I am having a runtime error.
我正在通过分散模型、蓝图来重构我的 Flask 应用程序,但我遇到了运行时错误。
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
I have the following problem(the sample project are hosted here: https://github.com/chfw/sample):
我有以下问题(示例项目托管在这里: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
I did a research on this topic. The re-factoring is suggested here:
我对这个主题进行了研究。这里建议重新分解:
Flask-SQLAlchemy import/context issue
The same problem was raised here:
这里提出了同样的问题:
And the above thread(2010) suggested a hack like this:
上面的线程(2010)建议了一个这样的黑客:
app.register_blueprint(api)
db.app=app #<------------<<
db.init_app(app)
Did anyone know how to do this properly? How did you solve it?
有谁知道如何正确地做到这一点?你是怎么解决的?
Thanks
谢谢
采纳答案by Mark Hildreth
This has to do with Flask's application context. When initialized with db.init_app(app)
, Flask-SQLAlchemy doesn't know which app is the "current" app (remember, Flask allows for multiple appsin the same interpreter). You could have multiple apps using the same SQLAlchemy
instance in the same process, and Flask-SQLAlchemy would need to know which is the "current" one (due to Flask's context localnature of everything).
这与 Flask 的应用程序上下文有关。当用 初始化时db.init_app(app)
,Flask-SQLAlchemy 不知道哪个应用程序是“当前”应用程序(请记住,Flask 允许在同一个解释器中使用多个应用程序)。您可以SQLAlchemy
在同一进程中使用多个应用程序,并且 Flask-SQLAlchemy 需要知道哪个是“当前”应用程序(由于 Flask 的上下文本地特性)。
If you need to do this during runtime, you must explicitly say which app is the "current" app for all calls. You can do this by changing your code to use a with app.app_context()
block:
如果您需要在运行时执行此操作,您必须明确说明哪个应用程序是所有调用的“当前”应用程序。您可以通过更改代码以使用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
If you are writing a standalone script that needs the app context, you can push the context at the beginning rather than putting everything in a with
block.
如果您正在编写需要应用程序上下文的独立脚本,您可以在开始时推送上下文,而不是将所有内容都放在一个with
块中。
create_app().app_context().push()
If you write a command for Flask's clithe command will automatically have access to the context.
如果您为 Flask 的cli编写命令,该命令将自动访问上下文。
回答by John Lockwood
Mark's answer was great and it helped me a lot. However, another way to approach this is to run the code that relies on the app context in a function decorated with @app.before_first_request. See http://flask.pocoo.org/docs/0.10/appcontext/for more information. That's in fact how I ended up doing it, largely because I wanted to be able to call the initialization code outside of flask as well, which I handle this way.
马克的回答很棒,对我帮助很大。但是,解决此问题的另一种方法是在用@app.before_first_request 修饰的函数中运行依赖于应用程序上下文的代码。有关更多信息,请参阅http://flask.pocoo.org/docs/0.10/appcontext/。事实上,这就是我最终这样做的方式,主要是因为我也希望能够在 Flask 之外调用初始化代码,我是这样处理的。
In my case I want to be able to test SQLAlchemy models as plain SQLAlchemy models without Flask-SQLAlchemy, though the db in the code below is simply a (Flask) SQLAlchemy db.
在我的情况下,我希望能够将 SQLAlchemy 模型作为没有 Flask-SQLAlchemy 的普通 SQLAlchemy 模型进行测试,尽管下面代码中的 db 只是一个(Flask)SQLAlchemy db。
@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