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 [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.
"""
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()