I created a class CorrelatedProxy inheriting from AssociationProxy that
allows the creator function to depend on the owner instance of the
association proxy. Essentially it gets a attribute 'correlator' of the
something like lambda x: lambda y, z: Constructor(x, y, z), and then
intercepts the __get__ of AssociationProxy to create self.creator on the
fly by applying the owner instance to the correlator. Now consider the code
below.
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative.api import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.orm.collections import attribute_mapped_collection
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import Integer
from sqlalchemy.ext.associationproxy import AssociationProxy
class CorrelatedProxy(AssociationProxy):
def __init__(self, *args, **kw):
self.correlator = kw.pop('correlator', None)
AssociationProxy.__init__(self, *args, **kw)
def __get__(self, obj, class_):
if obj:
self.creator = self.correlator(obj)
return AssociationProxy.__get__(self, obj, class_)
def correlated_proxy(*args, **kw):
return CorrelatedProxy(*args, **kw)
Base = declarative_base()
class A(Base):
__tablename__ = 'table_a'
id = Column(Integer, primary_key=True)
ab = relationship('AB', backref = 'a',
collection_class=attribute_mapped_collection('b'))
abnum = correlated_proxy('ab', 'num', correlator=\
lambda a: lambda b, n: AB(a=a, b=b, num=n))
class AB(Base):
__tablename__ = 'table_ab'
num = Column(Integer)
a_id = Column(Integer, ForeignKey('table_a.id'), primary_key=True)
b_id = Column(Integer, ForeignKey('table_b.id'), primary_key=True)
class B(Base):
__tablename__ = 'table_b'
id = Column(Integer, primary_key=True)
ab = relationship('AB', backref = 'b',
collection_class=attribute_mapped_collection('a'))
if __name__ == '__main__':
engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(engine)
session = Session()
Base.metadata.create_all(engine)
aa = A()
bb = B()
aa.abnum[bb] = 1
assert aa.abnum[bb] == aa.abnum[None] == 1
Basically, no matter, what I do, any time I assign something to the
CorrelatedProxy, everything goes normally except that 'None' always becomes
a key, assigned to the last value I assigned to the proxy. I tried
debugging and tracing, but there's some quantum effect going on where if I
inspect some value, some other value changes. I for the life of me can't
figure out why it's doing this. I'm guessing it's some Instrumentation
effect of SA, but I don't understand the in and outs of that very much. I
currently can work around this by filtering out the None, but it'd be nice
to know why this occurs and whether it will affect any other elements of my
program with whatever is going on underneath.
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.