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.