我在现有的mysql数据库中反映了一大堆表。我想表示任何表中某个名称的任何列都默认为datetime.now()。然而,天真地循环遍历表和列,只是在我发现具有某个名称的那些上设置默认值不起作用,在执行session.add()时; session.flush()我收到以下错误:
AttributeError: 'builtin_function_or_method' object has no attribute '__visit_name__'
这似乎与调用_set_parent(以及sqlalchemy.schema中第721行的self._init_items(*toinit)
)有关。
有没有人知道是否有办法做到这一点,既没有通过我所有的反射表,也没有添加Column(..)行,所有这些都做同样的事情或诉诸真正丑陋的黑客?
答案 0 :(得分:6)
另一种选择是在反映时覆盖需要默认值的列:
Table('some_table', metadata,
Column('create_time', DateTime, default=datetime.now),
autoload=True)
不幸的是,您目前无法反映数据类型并同时设置SQLAlchemy端默认值。有人可能会争辩说,数据类型是接口定义的一部分,因此冗余不会产生维护问题 - 如果列数据类型发生更改,则您很可能也需要更改默认值函数。
答案 1 :(得分:5)
好的,我已经解决了这个问题,这是一个中等可怕的黑客,因为我使用的是内部方法。你需要这样做:
from sqlalchemy.schema import ColumnDefault
#....
ColumnDefault(callable)._set_parent(column)
这会产生所需的行为。请注意,您也可以传递ColumnDefault的kwarg for_update = True,这将改变行为以在UPDATE上更改而不是插入。
我觉得很脏: - (
答案 2 :(得分:3)
五年后,您可以使用事件监听器[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