在所有模型中共享事件处理程序

时间:2012-09-28 12:56:38

标签: python sqlalchemy

我正在尝试在所有模型中共享一个简单的功能(时间戳),并按照SQLA文档中的描述使用“扩充基础”方法。到目前为止,我做到了这一点:

import sqlalchemy as sa
from datetime import datetime as dt

class EntityBase(object):

    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    id = sa.Column(sa.Integer, primary_key=True)
    last_update = sa.Column(sa.DateTime, default=dt.utcnow())

def update_entity(mapper, connection, target):
    target.last_update = dt.utcnow()


Entity = declarative_base(cls=EntityBase)

sa.event.listen(Entity, 'before_insert', update_entity)
sa.event.listen(Entity, 'before_update', update_entity)

我的所有模型都来自Entity类。但在运行时我得到sqlalchemy.orm.exc.UnmappedClassError: Class 'sqlalchemy.ext.declarative.Base' is not mapped。我究竟做错了什么?

更新 我通过简单的预处理来避免这个问题,如下所示:

def setupEntities():
    ...
    for cls in Entity.__subclasses__():
        listen(cls, 'before_insert', update_entity)
        listen(cls, 'before_update', update_entity)
    ...

...但我想知道正确的方法。

1 个答案:

答案 0 :(得分:1)

有趣的是,你上面的方式可能应该工作。这会很方便。所以我为http://www.sqlalchemy.org/trac/ticket/2585添加了一张票。

目前,您可以这样做的方法是为您的Base设置新映射的事件侦听器:

Entity = declarative_base(cls=EntityBase):

from sqlalchemy.orm import mapper
@event.listens_for(mapper, 'mapper_configured')
def set_events(mapper, class_):
   if issubclass(class_, Entity):
        listen(class_, 'before_update', update_entity)
        listen(class_, 'before_insert', update_entity)

事实上如果我为#2585实现这个功能,我可能也必须这样做。