2012-09-06 38 views
2

我在一個腳本中使用SA,我將用它來定期將'生產'副本中的一部分mysql表'複製'到dev/test系統。我寫了代碼來簡單地反映源表和meta.create_all(destination_engine)。由於FK的性質,我現在知道我需要將use_alter=True應用於表中的ForeignKeys,因爲我創建了這些表,因此我不會收到CircularDependencyErrors或其他問題。我需要假設我不知道有多少FK或他們的名字,直到我通過元數據。SQLAlchemy動態覆蓋反射列

我是新來的SA和通常的Java程序員(你會告訴:D)。我試圖改變use_alter屬性。反覆起初:

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()不會引發CircularDependencyError後,我設置use_alter屬性就像我上面做的是很重要的。如果我刪除該代碼,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選項他們各自的外鍵?我在想這個錯誤的方式嗎?

回答

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都適合您。

* 更新:*使用此方法已通過同行評審,現在被用作生產代碼。似乎運作良好!