[英]Flask-SQLAlchemy using global DB instance
这是我所做的:
from flask import Flask
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
dbhost = 'localhost'
dbuser = 'user'
dbpass = 'password'
dbname = 'db'
DBUri = 'mysql://%s:%s@%s/%s?charset=utf8'%(dbuser,dbpass,dbhost,dbname)
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = (DBUri)
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
# an Engine, which the Session will use for connection
# resources
engine = create_engine(DBUri)
# create a configured "Session" class
Session = sessionmaker(bind=engine)
# create a Session
DBsession = Session()
和
@sched.cron_schedule(second='*/5')
def some_decorated_task():
date_now = datetime.datetime.now().date()
for item in DBsession.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)):
print item.id, item.server_users.native_linux_user
有一个表user_groups_n_hosts上面的代码是一个每30秒运行一次的函数。
我的问题是,如果那时user_groups_n_hosts有10条记录,那么一旦我启动Flask应用程序,则无论从外部在表user_groups_n_hosts中插入多少记录,以上代码都将继续打印10条记录。 换句话说,我认为我的函数具有表的某些实例,这些实例仅在应用程序初始化的开始时进行初始化。 我知道我在做一些愚蠢的事情。 请有人指出。
代替DBsession.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)):
我试过了user_groups_n_hosts.query.filter(user_groups_n_hosts.end_time < str(date_now)):
但是结果是一样的。
您的过滤器user_groups_n_hosts.end_time <str(date_now)将日期与字符串进行比较。
另外,您应将会话视为按请求的事物,而不是应用程序中的持久实体。
考虑到这一点,请尝试更改
@sched.cron_schedule(second='*/5')
def some_decorated_task():
date_now = datetime.datetime.now().date()
for item in DBsession.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)):
print item.id, item.server_users.native_linux_user
至
@sched.cron_schedule(second='*/5')
def some_decorated_task():
date_now = datetime.datetime.now().date()
sess = Session()
for item in sess.query(user_groups_n_hosts).filter(user_groups_n_hosts.end_time < str(date_now)):
print item.id, item.server_users.native_linux_user
sess.close()
您需要每次都建立一个新的交易。 您可以在每次运行时创建一个全新的会话对象,我们可以重用该会话,但是请确保在查询后对它进行commit()
, rollback()
或close()
。
该效果是由MySQL的某些默认策略引起的。
如果您将InnoDB用作MySQL的默认存储引擎,则它将REPEATABLE READ
用作其隔离级别。 这是默认设置,因为在大多数情况下,避免事务内部的不可重复读取是有意义的。 因此,如果不结束交易,您每次都会从数据库中获得相同的结果。
从SQLAlchemy文档 :
每当用于与数据库对话时,会话都会在开始通信后立即开始数据库事务。 假设自动提交标志保留为建议的默认值False,则此事务将一直进行到会话回滚,提交或关闭。 如果在上一交易结束后再次使用该会话,则该会话将开始新的交易; 由此可见,该会话可以跨许多事务使用,尽管一次只能进行一次。 我们将这两个概念称为事务作用域和会话作用域 。
不建议使用的另一个选项是使用autocommit=True
创建会话,该会话将在每个查询语句之后自动提交事务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.