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). 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 sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.