I’m trying to share a simple functionality across all my models (timestamping) and am going with the “augmenting the base” approach as described in SQLA docs. So far I did this:
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)
All my models are derived from the Entity class. But at runtime I get sqlalchemy.orm.exc.UnmappedClassError: Class 'sqlalchemy.ext.declarative.Base' is not mapped. What am I doing wrong?
UPDATE
I’ve circumvented the problem by doing simple preprocessing, like this:
def setupEntities():
...
for cls in Entity.__subclasses__():
listen(cls, 'before_insert', update_entity)
listen(cls, 'before_update', update_entity)
...
…but I’d like to hear about a right way to do it.
interesting here is that the way you did it above probably should work. It would be handy. So I’ve added a ticket for that http://www.sqlalchemy.org/trac/ticket/2585 .
For now, a way you can do this is to set an event listener for new mappings along with your Base:
in fact if I implement the feature for #2585 I’d probably have to do it very similarly to this also.