On Apr 7, 2011, at 1:53 PM, Lars wrote:

> Hi Michael,
> 
> I am trying to run the alternative you described in the article, but
> the following code is most likely from an old version of SA a don't
> know how to update (I am working with 6.6):
> 
>        mapper = class_mapper(cls)
>        table = mapper.local_table
>        mapper.add_property(attr_name, relationship(GenericAssoc,
> backref=backref('_backref_%s' % table.name, uselist=False)))
> 
> class_mapper is unknown or moved.
> 
> What does it do/how can I fix this?

a working version is in the distro inside of examples/poly_assoc.   at some 
point I want to add a modernized version that uses declarative (its much easier 
to read).



> 
> Cheers, Lars
> 
> On Apr 6, 10:18 pm, Michael Bayer <[email protected]> wrote:
>> On Apr 6, 2011, at 5:43 AM, farcat wrote:
>> 
>>> Hello,
>> 
>>> I am experimenting with a pattern where records hold the table name
>>> and record id of the next record in any other table, chaining records
>>> in different tables. This works, but I can't figure out how to clean
>>> op references to the next record in another table when I delete a
>>> record (the pattern does not use foreign keys in the normal sense).
>> 
>> .. in that it doesn't use foreign keys.    Since you're working against the 
>> relational database's supported patterns, you'd need to roll the deletion of 
>> related rows yourself.    The pattern is also called a "polymorphic 
>> association" and I blogged about it years ago here:  
>> http://techspot.zzzeek.org/2007/05/29/polymorphic-associations-with-s....
>> 
>> 
>> 
>> 
>> 
>> 
>> 
>>> The code is:
>> 
>>> =====================================
>> 
>>> from sqlalchemy import *
>>> from sqlalchemy.orm.session import sessionmaker
>>> from sqlalchemy.ext.declarative import declarative_base,
>>> declared_attr, DeclarativeMeta
>>> #-------------------------------------------------------------------------- 
>>> -
>>> Base = declarative_base()
>>> reg = dict()
>>> engine = create_engine('sqlite:///:memory:', echo=False)
>>> Session = sessionmaker(bind = engine)
>>> #-------------------------------------------------------------------------- 
>>> -
>> 
>>> class chainmeta(DeclarativeMeta):
>>> #-------------------------------------------------------------------------- 
>>> -
>>>    class Base(object):
>>>        session = Session()
>>>        @declared_attr
>>>        def __tablename__(cls):
>>>            return cls.__name__
>> 
>>>        id = Column(Integer, primary_key = True)
>>>        next_table = Column(String(64))
>>>        next_id = Column(Integer) #in table with name stored in
>>> next_table!
>> 
>>>        def __init__(self, data, next = None):
>>>            self.data = data
>>>            self.prev = None
>>>            self.next = next
>>>            self.session.add(self)
>>>            self.session.flush()
>> 
>>>        def _getnext(self):
>>>            if self.next_table and self.next_id:
>> 
>>>                return
>>> self.session.query(reg[self.next_table]).filter(self.next_id ==
>>> reg[self.next_table].id).one()
>>>            else: return None
>> 
>>>        def _setnext(self, next):
>>>            if next:
>>>                if self.next:
>>>                    self.next.prev = None
>>>                self.next_table = next.__tablename__
>>>                self.next_id = next.id
>>>                next.prev = self
>>>            elif self.next:
>>>                self.next.prev = None
>>>                self.next_table = None
>>>                self.next_id = None
>> 
>>>        def _delnext(self):
>>>            self.next.prev = None
>>>            self.next_table = None
>>>            self.next_id = None
>> 
>>>        next = property(_getnext, _setnext, _delnext)
>> 
>>>        def __repr__(self):
>>>            out = "type: " + type(self).__name__ + "["
>>>            for name in self.__dict__:
>>>                out += name + ", "
>>>            out += "]"
>>>            return out
>>> #-------------------------------------------------------------------------- 
>>> -
>>>    def __new__(mcls, name, coltype):
>>>        return DeclarativeMeta.__new__(mcls, name, (chainmeta.Base,
>>> Base),{"data": Column(coltype, nullable = False)})
>>>    def __init__(cls, name, coltype):
>>>        reg[name] = cls
>>>        return DeclarativeMeta.__init__(cls, name, (chainmeta.Base,
>>> Base),{})
>>> #-------------------------------------------------------------------------- 
>>> -
>>> if __name__ == '__main__':
>>>    Base.metadata.drop_all(engine)
>>>    session = chainmeta.Base.session = Session()
>> 
>>>    Ni = chainmeta("Ni", Integer)
>>>    Nb = chainmeta("Nb", Boolean)
>>>    Nt = chainmeta("Nt", String(200))
>>>    Base.metadata.create_all(engine)
>> 
>>>    ni1 = Ni(5)
>>>    ni2 = Ni(12)
>>>    nb1 = Nb(True)
>>>    nb2 = Nb(False)
>>>    nt1 = Nt("text in nt1")
>>>    nt2 = Nt("text in nt2")
>>>    ni1.next = ni2
>>>    ni2.next = nb1
>>>    nb1.next = nb2
>>>    nb2.next = nt1
>>>    nt1.next = nt2
>>>    nt2.next = ni1 #circular
>>>    print "OBJECTS"
>>>    n = ni1
>>>    count = 0
>>>    print "nexts: ................."
>>>    while n and count < 10:
>>>        print n.data
>>>        count += 1
>>>        n = n.next
>>>    n = ni1
>>>    count = 0
>>>    print "prevs: ................."
>>>    while n and count < 10:
>>>        print n.data
>>>        count += 1
>>>        n = n.prev
>>>    print
>>> "-------------------------------------------------------------------------- 
>>> ---------"
>>>    nts = session.query(Nt).all()
>>>    print "QUERIES"
>>>    for nt in nts:
>>>        print nt.data
>>>    print "+++++++++++++++++++++"
>>>    print session.query(Ni).filter(Ni.next_id ==
>>> nb1.id).first().data
>> 
>>> =====================================
>> 
>>> This might seem to have no reasonable us case, but it is something I
>>> want to use in a more complicated pattern later on. Basically the
>>> question is, how can I remove a record and have no next or prev
>>> pointing to it in other objects or records (without adding some sort
>>> of external controller)?
>> 
>>> Cheers, Lars
>> 
>>> --
>>> You received this message because you are subscribed to the Google Groups 
>>> "sqlalchemy" group.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to 
>>> [email protected].
>>> For more options, visit this group 
>>> athttp://groups.google.com/group/sqlalchemy?hl=en.
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "sqlalchemy" group.
> To post to this group, send email to [email protected].
> 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.
> 

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