在Flask-APScheduler作业中查询模型会引发应用上下文RuntimeError

22

我希望使用Flask-APScheduler运行一个任务,该任务会查询Flask-SQLAlchemy模型。当任务运行时,我会收到一个错误消息:RuntimeError: application not registered on db instance and no application bound to current context。如何运行一个可以查询数据库的任务。

from flask_apscheduler import APScheduler

scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
from models import User

def my_job():
    user = User.query.first()
    print(user)

在查询打印之前,错误发生了。在应用程序的其他查询中,数据库正常工作。

我尝试在设置扩展时添加with app.app_context():,但那没起作用。

with app.app_context()
    scheduler = APScheduler()
    scheduler.init_app(app)
    scheduler.start()

完整的回溯信息如下:

ERROR:apscheduler.executors.default:Job "run_in (trigger: interval[0:00:10], next run at: 2016-10-18 23:00:53 CEST)" raised an exception
Traceback (most recent call last):
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/apscheduler/executors/base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "/Users/user/Documents/myfolder/myfolder/myfile.py", line 19, in myjob
    user = User.query.all()
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 454, in __get__
    return type.query_class(mapper, session=self.sa.session())
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 71, in __call__
    return self.registry()
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/sqlalchemy/util/_collections.py", line 878, in __call__
    return self.registry.setdefault(key, self.createfunc())
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 704, in create_session
    return SignallingSession(self, **options)
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 149, in __init__
    self.app = db.get_app()
  File "/Users/user/.virtualenvs/myfolder/lib/python2.7/site-packages/flask_sqlalchemy/__init__.py", line 845, in get_app
    raise RuntimeError('application not registered on db '
RuntimeError: application not registered on db instance and no application bound to current context
2个回答

13

在执行查询时,Flask-SQLAlchemy需要一个活动的应用程序上下文。虽然Flask-APScheduler确实将APScheduler与Flask集成在一起,但在运行每个作业时它不会推送应用程序上下文。

您需要在作业中推送一个应用程序上下文。在设置扩展名时推送应用程序上下文不起作用。

def my_job():
    with app.app_context():
        ...

你可能想要一个应用程序上下文来运行所有的工作。你可以继承这个扩展并重写run_job

from flask_apscheduler import APScheduler as _BaseAPScheduler

class APScheduler(_BaseAPScheduler):
    def run_job(self, id, jobstore=None):
        with self.app.app_context():
            super().run_job(id=id, jobstore=jobstore)
            # super(APScheduler, self) in Python 2

5
我通过在应用工厂中强制使用单应用程序模式来解决了这个问题。从技术上讲,这并不正确,可能会在其他地方引起问题,但它解决了我的特定问题。
def create_app():
    new_app = Flask(__name__)
    db.init_app(new_app)
    db.app = new_app
    return new_app

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接