Flask-SQLAlchemy:如何在不触发数据库提交的情况下调用db.create_all()和db.drop_all()?

时间:2015-12-22 06:57:15

标签: sqlalchemy flask-sqlalchemy

我有一个相当标准的Flask-SQLAlchemy设置连接到PostgreSQL 9.4数据库。

出于测试目的,我想在数据库事务的范围内调用db.create_all(),运行我的测试,然后调用db.drop_all() - 所有这些都不提交数据库事务。这是可能的,因为PostgreSQL在事务中包装了DDL。

但是,每当我致电db.create_all()db.drop_all()时,Flask-SQLAlchemy会在创建每个个别表后发出COMMIT。同样,它在每个表被删除后发出COMMIT

我有COMMIT_ON_TEARDOWN = True,但AFAIK这应该只对最终提交有效 - 它不应该导致在每个表之后发生中间提交。

如何更改此行为以便在不自动触发数据库提交的情况下创建或删除表?

2 个答案:

答案 0 :(得分:1)

看起来sqlalchemy使用autocommit = True实现了create_all(),所以可能无法改变这种行为。

相关代码: https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/engine/base.py#L199

https://github.com/zzzeek/sqlalchemy/blob/859379e2fcc4506d036700ba1eca4c0ae526a8ee/lib/sqlalchemy/sql/ddl.py#L60

更新

对于不支持嵌套事务的MySQL,我的回答是正确的==> https://dev.mysql.com/doc/refman/5.7/en/implicit-commit.html。 正如@Jeff Widman在他的回答中提到的,有一种方法可以为PostgreSQL做“通过用嵌套事务中运行的全局会话替换全局会话”

答案 1 :(得分:0)

我是一个sqlalchemy noob,但这似乎可以解决问题:

with contextlib.closing(engine.connect()) as con:
    trans = con.begin()
    database.metadata.create_all(bind=con)
    trans.commit()