将触发器添加到SQLAlchemy Base Class

时间:2015-05-28 00:49:52

标签: python postgresql sqlalchemy

我正在为一个新的Postgres数据库创建一个SQLAlchemy基类,并希望将簿记字段合并到其中。具体来说,我希望自动更新modified_atmodified_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 docstable_name参数找到target但是当与Base.metadata一起使用时,它会返回MetaData(bind=None)而不是表格。< / p>

我非常希望将此功能作为Base的一部分,而不是将其包含在迁移中或外部以减少某人忘记添加触发器的可能性。这可能吗?

1 个答案:

答案 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)