SQLAlchemy,清除数据库内容但不删除架构

Jul*_*era 47 python pylons sqlalchemy

我正在开发一个基于exisitng数据库的Pylons应用程序,所以我正在使用反射.我有一个SQL文件,其中包含我用来创建测试数据库的模式.这就是为什么我不能简单地使用drop_allcreate_all.

我想写一些单元测试,我遇到了每次测试后清除数据库内容的问题.我只想删除所有数据,但保持表格完好无损.这可能吗?

该应用程序使用Postgres,这也是必须用于测试的内容.

akn*_*ds1 49

我在SQLAlchemy Google小组上询问了同样的事情,我得到了一个似乎运作良好的食谱(我的所有表都被清空了).请参阅该主题以供参考.

我的代码(摘录)看起来像这样:

import contextlib
from sqlalchemy import MetaData

meta = MetaData()

with contextlib.closing(engine.connect()) as con:
    trans = con.begin()
    for table in reversed(meta.sorted_tables):
        con.execute(table.delete())
    trans.commit()
Run Code Online (Sandbox Code Playgroud)

编辑:我修改了代码以相反的顺序删除表; 据说这应该确保在父母面前删除孩子.

  • `engine`来自哪里?和`contextlib`?它是标准库吗?如果进口完成,这个答案会更好. (10认同)
  • 它似乎工作!谢谢.我在Pylons中使用的确切代码是:`for reverse in table(meta.Base.metadata.sorted_tables):meta.Session.execute(table.delete()); meta.Session.commit()` (5认同)
  • 缺点是这种方法不适用于那些具有外键约束的表。 (3认同)
  • @MatthieuRodic,我怀疑您在此处的编辑会增加读者对此答案感到困惑的风险,而不是减少它。对于以前完成 SQLAlchemy 应用程序初始设置的读者来说,我认为它已经隐含地清楚什么是“meta”,因此编辑不会影响他们的理解。但是对于以前从未见过 `MetaData()` 并且只是在别人创建的应用程序中摸索的人来说,我担心现在的答案看起来像是他们应该创建一个 *new* `MetaData()` 实例与此代码一起使用,这当然不起作用。 (2认同)

kol*_*pto 12

对于PostgreSQL使用TRUNCATE:

with contextlib.closing(engine.connect()) as con:
    trans = con.begin()
    con.execute('TRUNCATE {} RESTART IDENTITY;'.format(
        ','.join(table.name 
                 for table in reversed(Base.metadata.sorted_tables))))
    trans.commit()
Run Code Online (Sandbox Code Playgroud)

注意:RESTART IDENTITY;确保所有序列也被重置.但是,这比DELETE@ aknuds1 的配方慢了50%.

另一个方法是首先删除所有表,然后重新创建它们.这又慢了50%:

Base.metadata.drop_all(bind=engine)
Base.metadata.create_all(bind=engine)
Run Code Online (Sandbox Code Playgroud)

  • metadata.Base.metadata.drop_all(bind = engine)给出错误AttributeError:'MetaData'对象没有属性'Base' (2认同)