I use a MapperExtension to automatically put the current timestamp
into a updated_at column for all entities. This works fine except when
related entities get involved. Let's say I have a Many-To-One relation
between employees and departments. If I switch the department for an
employee, even though nothing has really changed for the department
instance, both employee and department instances will get a new
timestamp. I would like to know what is the best way to just update
the employee and skip the department.
Here's the sample code:
##########
from datetime import datetime
from dateutil.tz import tzlocal
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative import declarative_base,
DeclarativeMeta
from sqlalchemy.orm import relation, scoped_session, sessionmaker
from sqlalchemy.orm.interfaces import MapperExtension
from sqlalchemy.schema import Column, ForeignKey, MetaData
from sqlalchemy.types import DateTime, String
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
metadata.bind = engine
Session = scoped_session(sessionmaker())
class AuditMeta(DeclarativeMeta):
def __init__(cls, classname, bases, dict_):
dict_['updated_at'] = Column(DateTime(timezone=True))
return DeclarativeMeta.__init__(cls, classname, bases, dict_)
class AuditTracker(MapperExtension):
def before_update(self, mapper, connection, instance):
instance.updated_at = datetime.now(tzlocal())
class AuditEntity(object):
__mapper_args__ = {'extension': AuditTracker()}
AuditBase = declarative_base(name='AuditBase', cls=AuditEntity,
metaclass=AuditMeta, metadata=metadata)
class Employee(AuditBase):
__tablename__ = 'employees'
name = Column(String(50), primary_key=True)
department_name = Column(String(50),
ForeignKey('departments.name',
onupdate='cascade'),
nullable=True, index=True)
department = relation('Department', backref='employees')
class Department(AuditBase):
__tablename__ = 'departments'
name = Column(String(50), primary_key=True)
metadata.create_all()
employee = Employee(name='Mary')
department = Department(name='Accounting')
Session.add(employee)
Session.add(department)
Session.commit()
employee.department = department
Session.commit()
print employee.updated_at
print department.updated_at # how to make this None?
##########
By the way, the actual database got a lot of related entities, and
deadlocks were happening everywhere since I added the MapperExtension.
Haven't seen one for years :)
Regards,
Yap
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---