attached is an approach that uses just the tiniest amount of
awareness of how a mapper works, to do the whole optimized loading
scenario ahead of time, and you get an object with your two distinct
pro and con relationships, no list decoration or anything
needed. the appropriateness of this approach comes from the fact
that your optimization case is a load-time optimization, therefore
put the complexity at load time (which is easier to deal with since
it doesnt have to be concerned with collection mutability).
--~--~-~--~~~---~--~~
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
-~--~~~~--~~--~--~---
from sqlalchemy import *
class SomeClass(object):pass
class Position(object):
def __init__(self, data, type):
self.data = data
self.type = type
metadata = BoundMetaData('sqlite://', echo=True)
t1 = Table(t1, metadata,
Column('id', Integer, primary_key=True),
Column('data', String(30)))
t2 = Table('t2', metadata,
Column('id', Integer, primary_key=True),
Column('parent_id', Integer, ForeignKey('t1.id')),
Column('data', String(30)),
Column('type', String(20))
)
metadata.create_all()
class MyExt(MapperExtension):
def populate_instance(self, mapper, context, row, instance, identitykey, isnew):
# tell the mapper to populate the instance like it always does
mapper.populate_instance(context, instance, row, identitykey, isnew)
# get the row decorator that will translate the eager loaded row to something
# based off the columns in t2
decorator = context.attributes[id(mapper.props['_positions'].strategy)]
row = decorator(row)
# determine pro or con - create instance and append to either collection
if row[t2.c.type] == 'pro':
instance.pro.append(class_mapper(Position)._instance(context, row, None))
elif row[t2.c.type] == 'con':
instance.con.append(class_mapper(Position)._instance(context, row, None))
# alternatively! get the instance that was just appended to _positions
# if _positions[-1].type == 'pro':
# instance.pro.append(_positions[-1])
# ...etc
# tell the calling mapper populate_instance is taken care of
return None
mapper(SomeClass, t1, extension=MyExt(), properties={
'_positions':relation(Position, lazy=False, viewonly=True),
'pro':relation(Position, lazy=None, primaryjoin=and_(t1.c.id==t2.c.parent_id,t2.c.type=='pro')),
'con':relation(Position, lazy=None, primaryjoin=and_(t1.c.id==t2.c.parent_id,t2.c.type=='con'))
})
mapper(Position, t2)
sess = create_session()
sc =SomeClass()
sc.pro.append(Position(tastes great, pro))
sc.pro.append(Position(less filling, pro))
sc.con.append(Position(beer sucks, con))
sess.save(sc)
sess.flush()
sess.clear()
sc = sess.query(SomeClass).get(sc.id)
assert [x.data for x in sc.pro] == [tastes great, less filling]
assert [x.data for x in sc.con] == [beer sucks]
On Apr 16, 2007, at 8:00 PM, jason kirtland wrote:
Michael wrote:
On Apr 12, 2007, at 2:03 PM, jason kirtland wrote:
[...]
This does work, but because relation updates are happening
outside of the InstrumentedList (i.e. not on 'analysis'
directly), I'm losing the events that would normally be
triggered. I don't think I can manually manage them either, as
they're private __methods on InstrumentedList.
some ideas which im not sure if theyd work, one is to not use
collection_class and to go with an approach that is more like
the AssociationProxy - i.e. pro and con have special
collections on them which proxy to the utlimate associations
colleciton, but on top of the InstrumentedList instead of
underneath it the way collection_class does.
I've got a new implementation that uses this approach and it does
work- but it is even more complex. If the InstrumentedCollection
refactor (#213) allows implementors to choose when to fire add/del
events I think this sort of pattern can be made pretty simple.
On that front, I think it would be super useful if future
InstrumentedCollection classes have access to their relation()
arguments- e.g. a DRY ordered collection that keys off the
relation's order_by. A chance to error out at definition time
would be useful too.
-jek
--~--~-~--~~~---~--~~
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 sqlalchemy-
[EMAIL PROTECTED]
For more options, visit this group at