繁体   English   中英

使用全局数据库实例的Flask-SQLAlchemy

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM