SQLAlchemy动态覆盖反射列

时间:2012-09-06 15:27:15

标签: mysql reflection sqlalchemy python-2.7

我在一个脚本中使用SA,我将用它定期将一个mysql表的子集从'production'副本'复制'到dev / test系统。我编写的代码只是为了反映源表和meta.create_all(destination_engine)。由于FK的性质,我现在知道我需要在创建它们时将use_alter=True应用于表上的ForeignKeys,这样我就不会得到CircularDependencyErrors或其他问题。在我浏览元数据之前,我需要假设我不知道有多少FK或他们的名字。

我是SA的新手,通常是Java程序员(正如你所说的那样:D)。我试图改变use_alter attr。首先迭代地说:

tablesd = smeta.tables.items()
for tname, t in tablesd:
    for c in t.columns:
       for fk in c.foreign_keys:
            fk.use_alter = True
smeta.create_all(to_engine)

编辑:重要的是要注意,在设置use_alter属性后,create_all()不会像我上面那样抛出CircularDependencyError。如果我删除该代码,create_all()不起作用。它似乎并没有从创建中删除FK ......

这显然不起作用。然后,我在SA文档中阅读Overriding Reflected Columns,示例为:

mytable = Table('mytable', meta,
Column('id', Integer, primary_key=True), # override reflected 'id' to have primary key
Column('mydata', Unicode(50)),    # override reflected 'mydata' to be Unicode,   autoload=True)

我猜是单独反映每个表,然后在FK定义中添加use_alter=True会起作用,但我不能假设名称和值或FK /列的#。我读了很多关于使用DeclarativeBase来做这样的事情,但我不确定那会怎么做......

如何获取我的任意表列表,反映它们,然后在各自的外键上覆盖use_alter选项?我是否以错误的方式思考这个问题?

1 个答案:

答案 0 :(得分:5)

答案最终出现在问题中(想象一下......)。虽然每个ForeignKey对象都有一个use_alter值可以设置,但Constraints也有一个可以设置的单独属性(我无法在API Documentation中找到它在通过PyDev的调试器运行之后,我注意到前者已被设置,但与Constraints相关联的所有键仍然是False。我将它们设置为true:

for fk in table.foreign_keys:
    fk.use_alter=True
    fk.constraint.use_alter=True

这似乎产生了我正在寻找的SQL,并且没有CircularDependencyErrors并且metadata.sorted_tables似乎没有错误地正常创建表。我实际上能够重构我的代码并以 RIGHT 的方式做事!

对于任何想要使用SQLAlchemy进行DB - > DB反映复杂FK的人来说,这个答案和Tyler Lesmann's article都适合你。

* 更新:* 使用此方法已通过同行评审,现在正用作生产代码。似乎运作良好!