Hi Michael I made a simplified but I think for the ORM equivalent example which I attach. In ExamplesTest.py I commented: # essential: ORM canot cope if this comes after s._mother = m
It seems if that condition is not met then there is indefinite recursion. Whether that could/should be avoided by the ORM I do not know. I just noticed a mistake. Need to add to ExamplesOrm.py: mapper(OldSon, inherits=son_mapper, polymorphic_identity='oldson') This did not change the test results. Thanks for your time Ernst > Michael Bayer: >Its impossible for me to assist you further without the benefit of a complete >example of what you're doing, including both tables, both >mappers, an example >of their manipulation. If you attach a test case make sure its self >contained and does not rely on external >libraries other than SQLAlchemy. >There should not be recursion issues in SQLAlchemy but its possible that in >some cases they are >unavoidable, if things are configured to point to >themselves in some way (though I cannot picture how you'd be doing that >without >full details). -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@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.
""" doubly linked one to one reationship """ class Mother(object): #============== def __init__(self, son): self._son = son self._givenName = '' def __str__(self): return self.__class__.__name__+'('+self._givenName+' has son '+self._son._givenName+')' class Son(object): #============== def __init__(self): self._mother = None self._givenName = '' def __str__(self): return self.__class__.__name__+'('+self._givenName+' has mother '+self._mother._givenName+')' class YoungSon(Son): pass #============== class OldSon(Son): pass #==============
from Examples import * from sqlalchemy import Table, Column, Integer, String, Boolean, Date, MetaData, Sequence, ForeignKey, create_engine from sqlalchemy.orm import mapper, relation, backref """ One to one relationship mother and son (only ever one and only one son!) In objects: aMother._son aSon._mother """ def mappings(metadata): mothers_table = Table('mothers', metadata, Column('id',Integer, primary_key=True), # not in object Column('son', Integer, ForeignKey('sons.id')), # not in object Column('_givenName', String(40)) ) sons_table = Table('sons', metadata, Column('id',Integer, primary_key=True), # not in object Column('type', String(30),nullable=False), # not in object Column('_givenName', String(40)) ) mapper(Mother, mothers_table, properties={ '_son':relation(Son, backref=backref('_mother', uselist=False)) }) son_mapper = mapper(Son, sons_table, polymorphic_on=sons_table.c.type, polymorphic_identity='son') mapper(YoungSon, inherits=son_mapper , polymorphic_identity='youngson')
#!/usr/bin/python # vim: set fileencoding=UTF-8 : import os import unittest from Examples import * import ExamplesOrm from sqlalchemy.orm import sessionmaker, clear_mappers from sqlalchemy import create_engine, MetaData import transaction class ApplicationTest(unittest.TestCase): def setUp(self): """return db session object after creating the database schema according to ORM """ orm = ExamplesOrm self.engine = create_engine('sqlite:///:memory:') #overwritting what TG2 may have! #self.engine = create_engine('sqlite:///%(here)s/devdata.db') #overwritting what TG2 may have! #print "setUp BEFORE os.path.exists('devdata.db')", os.path.exists('devdata.db') #self.engine = create_engine('sqlite:///devdata.db') #overwritting what TG2 may have! self.metadata = MetaData(self.engine) Session = sessionmaker() Session.configure(bind=self.engine) self.session = Session() orm.mappings(self.metadata) self.metadata.create_all(bind=self.engine) transaction.commit() #print "setUp AFTER os.path.exists('devdata.db')", os.path.exists('devdata.db') def tearDown(self): #print "tearDown BEFORE os.path.exists('devdata.db')", os.path.exists('devdata.db') clear_mappers() self.metadata.drop_all(bind=self.engine) self.session.close() #print "tearDown AFTER os.path.exists('devdata.db')", os.path.exists('devdata.db') def _alternateSession(self): Session = sessionmaker() Session.configure(bind=self.engine) return Session() def testCreateSchema(self): #would be nice to list tables and columns created #the table exists and has no row in it self.assertTrue(self.session.query(Mother).count() == 0) def testDoublyLinkedOneToOne(self): s = Son() s._givenName = 'Albert' m = Mother(s) m._givenName = 'Maria' s._mother = m print m, s #now add self.session.add(m) self.session.commit() self.assertTrue(self.session.query(Mother).count() == 1) print self.session.query(Mother).first() print self.session.query(Mother).first()._son s = self._alternateSession() print s.query(Mother).first()._son._mother def testExchangeSon(self): s = Son() s._givenName = 'Albert' m = Mother(s) m._givenName = 'Maria' s._mother = m print m, s #now exchange s = Son() s._givenName = 'Paul' s._mother = m m._son = s print m, s def testInheritance(self): s = YoungSon() s._givenName = 'YoungJim' m = Mother(s) m._givenName = 'Maria' s._mother = m print m, s s = OldSon() m._son = s # essential: ORM canot cope if this comes after s._mother = m s._givenName = 'OldJohn' s._mother = m print m, s if __name__ == '__main__': unittest.main()