Auto-timestamping SQLAlchemy entities
There are a lot of cases when we want to track time when an entity was created or updated. Here is a simple recipe to make some or all of your SQLAlchemy entities auto-timestamping. To achieve this, we will provide a mixin class.
from datetime import datetime from sqlalchemy import Column, DateTime, event class TimeStampMixin(object): """ Timestamping mixin """ created_at = Column(DateTime, default=datetime.utcnow) created_at._creation_order = 9998 updated_at = Column(DateTime, default=datetime.utcnow) updated_at._creation_order = 9998 @staticmethod def _updated_at(mapper, connection, target): target.updated_at = datetime.utcnow() @classmethod def __declare_last__(cls): event.listen(cls, 'before_update', cls._updated_at)
This mixin class adds two columns,
updated_at, initialized with current timestamp. A static method _updated_at just updates the updated_at field for the target instance it receives. But the real magic is done in
__declare_last__ method. According to SQLAlchemy docs it gets called after the mapper is configured. The reason is that we cannot set a listener for an unmapped class, and mixin itself will never be mapped. We could add listeners for each entity directly, but we want some magic. So, this method adds a listener for before_update event for each derived class! And finally,
from sqlalchemy.ext.declarative import declarative_base class Base(TimeStampMixin): pass Base = declarative_base(cls=Base)
Just derive all your model entities from this custom Base class - and magic is here.