2009-06-02 23 views
1

我已經反映了在退出mysql數據庫中的表負載。我想表達任何表中某個名字的任何列都默認爲datetime.now()。然而,天真地循環遍歷表和列,只是設置默認的那些我發現有一個特定的名稱不起作用,當做session.add();調用Session.flush()我收到以下錯誤:在sqlalchemy反射表中覆蓋默認值

AttributeError: 'builtin_function_or_method' object has no attribute '__visit_name__' 

這似乎在呼叫被捆綁到_set_parent(與此self._init_items(*toinit)在行721 sqlalchemy.schema

有誰知道如果有辦法做到這一點,而不是通過所有的反射表,並添加列(..)行,每一個都做同樣的事情或訴諸真正醜陋的黑客?

回答

2

五年後,您可以使用事件監聽器[1]。你可以用一個函數註冊一個監聽器來運行:

def do_this_on_column_reflect(inspector, table, column_info): 
    column_name = column_info.get("name") 
    if column_name == "create_datetime": 
     column_info["default"] = datetime.now() 
event.listen(Table, "column_reflect", do_this_on_column_reflect) 

[1] http://docs.sqlalchemy.org/en/latest/core/events.html#sqlalchemy.events.DDLEvents.column_reflect [2] http://docs.sqlalchemy.org/en/latest/core/event.html#sqlalchemy.event.listen

5

好吧,我已經修復了這一點,這是一個相當可怕的黑客攻擊,因爲我使用了一種內部方法,你需要這樣做:

from sqlalchemy.schema import ColumnDefault 
#.... 
ColumnDefault(callable)._set_parent(column) 

這會產生所需的行爲。請注意,您也可以將ColumnDefault傳遞給kwarg for_update = True,您將改變行爲以更新UPDATE而不是插入。

我覺得髒:-(

5

另一種選擇是覆蓋需要違約,同時反映了列:

Table('some_table', metadata, 
    Column('create_time', DateTime, default=datetime.now), 
    autoload=True) 

很遺憾,目前不能反映數據類型,並在設定的SQLAlchemy側默認可以爭辯說,數據類型是接口定義的一部分,所以冗餘不會產生維護問題 - 如果列數據類型發生變化,您最有可能也需要更改默認值功能

+0

由於螞蟻,這肯定是我在每個表的基地首選方法,但是我一次反映多個表格,我想要一個規則適用於所有具有此特定列名稱的表格,所以我在下面將我的答案標記爲首選(如果是icky)答案。 – 2009-11-12 11:33:46