application not registered on db
前言
我在用Flask开发的时候,打算写个脚本用作cron定时执行。打算直接用flask中的model和sqlalchemy,并且有些代码可能会在应用中用到。代码终于写完了。。然后得到了错误”RuntimeError(‘application not registered on db ‘” and RuntimeError: application not registered on db instance and no application bound to current context。找到下面的文章
原文链接:http://piotr.banaszkiewicz.org/blog/2012/06/29/flask-sqlalchemy-init_app/
下面是翻译。
我最近正在重构我的Flask应用,并且其中一个最重要的改变是我用到了应用工厂模式。你可以发现很多不同(但类似)使用SQLAlchemy的语法结构。这里是其中一个最常见的:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
db.init_app(app)
db.create_all()
return app
然而,你应该偶然发现这么一个异常:
RuntimeError: application not registered on db instance and no application bound to current context
也许在你的测试用例中,使用db.create_all()
期间。
文档并没有对此问题有清楚的描述。经过漫长的寻找,我终于发现有三个办法可以解决此问题。
方法一
创建你的db
对象,并作为app
的一个参数:
def create_app():
app = Flask(__name__)
db = SQLAlchemy(app)
db.create_all()
return app
缺点是你没有一个全局的db
对象,并且导致你的蓝本无法工作。你将无法容易的创建models。
(顺便说:设置global db
加上db = SQLAlchemy(app)
,对我来说没有效果)
方法二
给db.app
分配创建好的应用:
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
db.init_app()
db.app = app
db.create_all()
return app
这个方法的缺点是:你可能会破坏db
内部源码。你不想这么做对吧?
(译者注:我是用这个办法解决了在脚本调用db
的问题。并且实际上这并不会破坏内部源码。)
方法三
在应用上下文里面调用db.create_all()
(这就是我们问题的所在)
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
db.init_app(app)
with app.test_request_context():
db.create_all()
return app
缺点是:这是test_request_context
(test!)。但是,毕竟,它对我来说很有效果,我的所有测试用例都通过了!
用你想用的方法。
如果你遇到了问题,并且用了不同的方法解决,请评论让我知道。
额外的提示
你需要在db.create_all
发生之前导入models本身:
with app.test_request_context():
from application.models import Post
db.create_all()
那么保持你的SQLAlchemy
对象实例放在不同的文件里,以皮面不会循环导入,是一个很好的主意:
# application/database.py
from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()
# application factory
from application.database import db
def create_app():
...
db.init_app(app)
...
# application/models.py
from application.database import db
class Post(db.Model):
...
博主后话
以上是翻译全文,后来我在查看db.init_app()
源码的时候,找到了get_app
函数,发现里面抛出的异常和译文描述的是一样的信息。说明异常是在这里抛出。
def get_app(self, reference_app=None):
"""Helper method that implements the logic to look up an application.
"""
if reference_app is not None:
return reference_app
if self.app is not None:
return self.app
ctx = connection_stack.top
if ctx is not None:
return ctx.app
raise RuntimeError('application not registered on db '
'instance and no application bound '
'to current context')
但是对于我来说,问题还是没有解决,因为我不是为了测试,事实上我的测试代码没有问题,我就是想在开发环境中测试一下。可以用原文中的方法二。但应该有更好的办法。
在stackoverflow中找到下面的答案:
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 apps in the same interpreter). You could have multiple apps using the sameSQLAlchemy
instance in the same process, and Flask-SQLAlchemy would need to know which is the “current” one (due to Flask’s context local nature of everything).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 do the following:
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.create_app().app_context().push()
If you write a command for Flask’s cli the command will automatically have access to the context.
他的方法二感觉就是我想要的,但不是很明白。
我加了也没有用。
app_ctx = app.app_context() app_ctx.push() stocks.main()#这里有数据库的读写操作。 app_ctx.pop()
实验来实验去都没有解决掉问题。暂时妥协了。也用了原作者的方法:
db.app = app#单独的任务,这么用也没啥问题。 stocks.main()#这里有数据库的读写操作。
Generic Cialis Tadalafil 20mg Statutaria Kamagra Vendite Levitra Drug Reviews [url=http://prilipills.com]dapoxetine price[/url] Comprar Cialis Generico En Sevilla Cephalexin For Horses Levitra On Line Sale
Difference Between Cialis And Viagra Amoxicillin And Clavulanate Potassium Dose Super Viagra Online [url=http://realviaonline.com]cialis 40 mg[/url] Can I Purchase Acticin Secure Ordering Acheter Misoprostol En Ligne
Propecia Pill 1 Mg Steigerung Der Potenz Cialis Levitra [url=http://cialiviag.com]cialis generic[/url] Propecia Donde Comprar Farmacias Prednisone Over The Counter Walgreens Buy Prednisolone Eu
Levitra 50 Mg Need Cialis Today Amoxicillin Vs Augmentin For Pediatric Sinusitis [url=http://realviaonline.com]generic 5mg cialis best price[/url] Risultati Finasteride Propecia
Amoxil 500mg With Food Propecia Y Dutasteride [url=http://drugs20.com]cialis without a doctor’s prescription[/url] Keflex Antibiotic For Spider Bites Cialis Ou Acheter Internet
Amoxicillin The Right Dose For Seniors Commande Viagra Canada Generika Cialis Kamagra [url=http://cialviag.com]cialis 20mg for sale[/url] Zithromax And Dairy Levitra Vardenafil Hydrochloride
24 Hour Amoxicillin Isotretinoin Skin Health On Line [url=http://fzlaka.com]tadalafil cialis from india[/url] Prix Propecia Toulouse Viagra 200 Mg For Sale Baclofene Pharmacodynamie