/ Published in: Python
Not sure if this is working or not?
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
""" Test of Versionable using extensions Why does the before_update or before_insert not cause the items added to the lists to save? If you call save twice they do? """ from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData('sqlite://') ####### class VersionExt(MapperExtension): """will update changes""" def before_update(self, mapper, connection, instance): instance._doversion() return EXT_CONTINUE def before_insert(self, mapper, connection, instance): instance._doversion() return EXT_CONTINUE version_table = Table("version", metadata, Column("id", Integer, primary_key=True), Column('assoc_id', None, ForeignKey('version_associations.assoc_id')), Column("whatchanged", String(255), nullable=False), Column("version", Integer), ) ## association table version_associations_table = Table("version_associations", metadata, Column('assoc_id', Integer, primary_key=True), Column('type', String(50), nullable=False), Column('version', Integer, default=0), ) class Version(object): def __init__(self, chg): self.whatchanged = chg member = property(lambda self: getattr(self.association, '_backref_%s' % self.association.type)) class VersionAssoc(object): def __init__(self, name): self.type = name def versionable(cls, name, uselist=True): """versionable 'interface'. """ mapper = class_mapper(cls) table = mapper.local_table mapper.add_property('version_rel', relation(VersionAssoc, backref='_backref_%s' % table.name)) if uselist: # list based property decorator def get(self): if self.version_rel is None: self.version_rel = VersionAssoc(table.name) return self.version_rel.versions setattr(cls, name, property(get)) else: # scalar based property decorator def get(self): return self.version_rel.versions[0] def set(self, value): if self.version_rel is None: self.version_rel = VersionAssoc(table.name) self.version_rel.versions = [value] setattr(cls, name, property(get, set)) mapper(Version, version_table) mapper(VersionAssoc, version_associations_table, properties={ 'versions':relation(Version, backref='association'), }) ###### # sample # 1, users users = Table("users", metadata, Column('id', Integer, primary_key=True), Column('name', String(50), nullable=False), # this column ties the users table into the change association Column('assoc_id', None, ForeignKey('version_associations.assoc_id')) ) class User(object): def _doversion(self): v1 = Version('what was changed?') self.versions.append(v1) v1.version = 1 print ' in _doversion ' mapper(User, users, extension=VersionExt()) versionable(User, 'versions', uselist=True) ###### # use it ! metadata.create_all() u1 = User() u1.name = 'bob' sess = create_session() sess.save(u1) sess.flush() # uncommenting these saves causes the versions to now be saved? # sess.save(u1) # sess.flush() sess.clear() # query objects, get their versions bob = sess.query(User).filter_by(name='bob').first() print [v.whatchanged for v in bob.versions] if bob.versions: print 'bob changed: %s ct = %s ' % (bob.versions[0].whatchanged, len(bob.versions)) else: print 'no versions'