我有一个使用Flask RESTful和Flask SQLAlchemy的python应用程序。我正在编写的API的一部分具有消散Timer对象的副作用。当Timer
过期时,它将执行一些数据库查询。我看到一个应该更新数据库中行(sqlite后端)的代码实际上没有发出任何UPDATE
语句的问题。我已通过打开SQLALCHEMY_ECHO
标志记录SQL语句来验证这一点。代码是否有效似乎是随机的。大约有一半的时间它未能发出UPDATE
语句。请参阅下面的完整示例。
我的猜测是,当从辅助线程调用SQLAlchemy Flask时,它无法正常工作。我认为Flask SQLAlchemy的重点之一是针对每个API请求为您管理SQLAlchemy session 。显然,由于Timer
过期时没有API请求继续进行,因此我可以看到某些地方可能无法正常工作。
为了测试这一点,我继续使用python的sqlite3 interface编写了一个简单的数据访问层,它似乎可以解决问题。
我确实宁愿不必重写一堆数据访问代码。在这种情况下,有没有办法让Flask SQLAlchemy正常工作?
样例代码
这是我设置flask应用程序并保存SQLAlchemy db
对象的地方:
from flask import Flask
from flask_restful import Api
from flask.ext.sqlalchemy import SQLAlchemy
from flask_cors import CORS
import db_conn
flask_app = Flask(__name__)
flask_app.config.from_object('config')
CORS(flask_app)
api = Api(flask_app)
db_conn.db = SQLAlchemy(flask_app)
api.add_resource(SomeClass, '/abc/<some_id>/def')
这是我创建ORM模型的方法:import db_conn
db = db_conn.db
class MyTable(db.Model):
__tablename__ = 'my_table'
id = db.Column(db.Integer, primary_key=True)
phase = db.Column(db.Integer, nullable=False, default=0)
def set_phase(self, phase):
self.phase = phase
db.session.commit()
这是带有计时器的API处理程序和失败的数据库调用:from flask_restful import Resource
from threading import Timer
from models import MyTable
import db_conn
import global_store
class SomeClass(Resource):
def put(self, some_id):
global_store.saved_id = some_id
self.timer = Timer(60, self.callback)
return '', 204
def callback(self):
row = MyTable.query.filter_by(id=global_store.saved_id).one()
# sometimes this works, sometimes it doesn't
row.set_phase(1)
db_conn.db.session.commit()
最佳答案
我猜在您的回调中,您实际上并没有更改对象的值。如果 session 状态不脏,SQLAlchemey将不会发出DB UPDATE调用。因此,如果由于某种原因该阶段已经为1,则无需执行任何操作。
关于python - 从辅助线程使用Flask SQLAlchemy,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41580029/