【问题标题】:SQLAlchemy override reflected columns dynamicallySQLAlchemy 动态覆盖反射列
【发布时间】:2012-08-31 11:19:07
【问题描述】:

我在脚本中使用 SA,我将使用该脚本定期将 mysql 表的子集从“生产”副本“复制”到开发/测试系统。我编写了代码来简单地反映源表和meta.create_all(destination_engine)。由于 FK 的性质,我现在知道我需要在创建表时将 use_alter=True 应用于表上的 ForeignKey,这样我就不会遇到 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)

编辑: 重要的是要注意 create_all() 在我像上面那样设置 use_alter 属性后不会抛出 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 选项?我是不是想错了?

【问题讨论】:

    标签: mysql reflection sqlalchemy python-2.7


    【解决方案1】:

    答案最终在问题内部(想象一下……)。虽然每个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,并且表被正确创建,没有 CircularDependencyErrorsmetadata.sorted_tables 似乎工作正常,没有错误。我实际上能够重构我的代码并以正确的方式做事!

    对于希望使用 SQLAlchemy 使用复杂 FK 进行 DB 反射的任何人,此答案和 Tyler Lesmann's article 适合您。

    *更新:* 使用此方法已通过同行评审,现在正在用作生产代码。看起来效果不错!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-21
      • 2010-10-30
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多