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, created_at
and 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.