我正在为一个新的Postgres数据库创建一个SQLAlchemy基类,并希望将簿记字段合并到其中。具体来说,我希望自动更新modified_at
和modified_by
两列。我能够找到如何为单个表执行此操作,但似乎使这部分基类变得更加棘手。
我的第一个想法是尝试利用declared_attr
功能,但我实际上并不想让触发器成为模型中的属性,因此看起来不正确。然后我看了使用event.listen
添加触发器:
trigger = """
CREATE TRIGGER update_{table_name}_modified
BEFORE UPDATE ON {table_name}
FOR EACH ROW EXECUTE PROCEDURE update_modified_columns()
"""
def create_modified_trigger(target, connection, **kwargs):
if hasattr(target, 'name'):
connection.execute(modified_trigger.format(table_name=target.name))
Base = declarative_base()
event.listen(Base.metadata,'after_create', create_modified_trigger)
我认为我可以使用显示in the docs的table_name
参数找到target
但是当与Base.metadata
一起使用时,它会返回MetaData(bind=None)
而不是表格。< / p>
我非常希望将此功能作为Base的一部分,而不是将其包含在迁移中或外部以减少某人忘记添加触发器的可能性。这可能吗?
答案 0 :(得分:2)
我能够在同事的帮助下解决这个问题。返回的MetaData
对象确实有一个表列表。这是工作代码:
modified_trigger = """
CREATE TRIGGER update_{table_name}_modified
BEFORE UPDATE ON {table_name}
FOR EACH ROW EXECUTE PROCEDURE update_modified_columns()
"""
def create_modified_trigger(target, connection, **kwargs):
"""
This is used to add bookkeeping triggers after a table is created. It hooks
into the SQLAlchemy event system. It expects the target to be an instance of
MetaData.
"""
for key in target.tables:
table = target.tables[key]
connection.execute(modified_trigger.format(table_name=table.name))
Base = declarative_base()
event.listen(Base.metadata, 'after_create', create_modified_trigger)