Hello;

Does anyone know what the behavior for the before_update and
before_insert methods of a mapper that is extended should be?  From
the code below, if i add a child object to an item being saved during
a before_insert that has a mapper extension it is not saved, but is if
session.save() is subsequently called?   However changes made to the
core attributes are saved, just not list items.  Is that the expected
behavior?  If so is there an earlier event to catch and do an
equivalent?

I posted the code online if it is too hard to read here:
http://demisauce.googlecode.com/svn/trunk/projects/demisauce/trunk/demisauce/tests/versionable.py

Thanks

Aaron




"""
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


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'


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to