Revision: 3881
Initial Code
Initial URL
Initial Description
Initial Title
Initial Tags
Initial Language
at September 27, 2007 23:54 by arski7
Initial Code
"""
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'
Initial URL
Initial Description
Not sure if this is working or not?
Initial Title
SqlAlchemy Versionable
Initial Tags
Initial Language
Python