Thanks for the pointer about remote_side.
In my application, the table definitions are not visible at runtime,
and the class definitions are autoloaded from the engine. So, I can't
say remote_side=table.c.id because table is not available. I do have
this solution that works well:
class People(Base):
__tablename__ = 'people'
__table_args__ = {'autoload':True}
People.children = relation(People, cascade="all",
backref=backref("parent", remote_side=[People.id]))
but I am wondering if I can move the definition of children into the
class somehow. Using this form:
class People(Base):
__tablename__ = 'people'
__table_args__ = {'autoload':True}
children = relation(People, cascade="all",
backref=backref("parent", remote_side=[People.id]))
gives a compile time error because People is being referenced before
it is completely defined. Trying to quote the word People (as either
'People' or 'people') also gives various runtime errors. I can
certainly live with adding the relation after defining the class, but
it would be cleaner to embed the relation in the class definition if
possible.
On Nov 11, 2:37 pm, Michael Bayer <[EMAIL PROTECTED]> wrote:
> always use remote_side=table.c.id on the "many to one" side of a self
> referential relation, in the case of declarative it would look like
> "remote_side=id".
> Seehttp://www.sqlalchemy.org/docs/05/mappers.html#advdatamapping_relatio...
> for information on this.
>
> On Nov 11, 2008, at 2:15 PM, MikeCo wrote:
>
>
>
> > I have a table that defines a self-referential hierarchy. My problem
> > is figuring out how to specify that relationship in declarative
> > syntax. From reading the documentation and looking at example
> > basic_tree.py, I think I understand it when using tables and mappers,
> > but can't get it right with declarative.
>
> > Here is one way I tried it. Using 0.5rc2 or 0.5rc3 gives the traceback
> > below on session.commit() telling me I have circular references.
>
> > import sqlalchemy
> > print 'SQLAlchemy version', sqlalchemy.__version__
>
> > from sqlalchemy import create_engine, Column, Integer, String,
> > MetaData, ForeignKey
> > from sqlalchemy.ext.declarative import declarative_base
> > from sqlalchemy.orm import sessionmaker, relation, backref
>
> > engine = create_engine(r'sqlite:///:memory:')
> > Base = declarative_base(bind=engine)
> > class People(Base):
> > __tablename__ = 'people'
> > id = Column(Integer, primary_key=True)
> > parent_id = Column(Integer, ForeignKey('people.id'))
> > name = Column(String)
> > parent = relation('People', cascade='all',
> > backref=backref('children'))
>
> > Base.metadata.create_all()
> > Session = sessionmaker()
> > session = Session()
>
> > p1 = People(name='john')
> > p2 = People(name='susie')
> > p3 = People(name='joannie')
> > p1.children.append(p2)
> > p2.children.append(p3)
> > session = Session()
> > session.add(p1)
> > session.commit()
>
> > File "sample_recursive.py", line 30, in <module>
> > session.commit()
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\session.py", line 670, in commit
> > self.transaction.commit()
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\session.py", line 375, in commit
> > self._prepare_impl()
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\session.py", line 359, in _prepare_impl
> > self.session.flush()
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\session.py", line 1361, in flush
> > self._flush(objects)
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\session.py", line 1431, in _flush
> > flush_context.execute()
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\unitofwork.py", line 261, in execute
> > tasks = self._sort_dependencies()
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\unitofwork.py", line 302, in _sort_depen
> > dencies
> > for t in task._sort_circular_dependencies(self,
> > [self.get_task_by_mapper(i) for i in cycles]):
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\orm\unitofwork.py", line 568, in _sort_circu
> > lar_dependencies
> > head = topological.sort_as_tree(tuples,
> > object_to_original_task.keys())
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\topological.py", line 58, in sort_as_tree
> > return _organize_as_tree(_sort(tuples, allitems,
> > allow_cycles=with_cycles))
> > File "C:\Python25\lib\site-packages\sqlalchemy-0.5.0rc2-py2.5.egg
> > \sqlalchemy\topological.py", line 212, in _sort
> > raise CircularDependencyError("Circular dependency detected " +
> > repr(edges) + repr(queue))
> > sqlalchemy.exc.CircularDependencyError: Circular dependency detected
> > [(<sqlalchemy.orm.identity.IdentityManagedState object
> > at 0x00E80510>, <sqlalchemy.orm.identity.IdentityManagedState object
> > at 0x00E80490>), (<sqlalchemy.orm.identity.IdentityMa
> > nagedState object at 0x00E80490>,
> > <sqlalchemy.orm.identity.IdentityManagedState object at 0x00E80510>),
> > (<sqlalchemy.orm.id
> > entity.IdentityManagedState object at 0x00E80490>,
> > <sqlalchemy.orm.identity.IdentityManagedState object at 0x00E80C70>),
> > (<
> > sqlalchemy.orm.identity.IdentityManagedState object at 0x00E80C70>,
> > <sqlalchemy.orm.identity.IdentityManagedState object at
> > 0x00E80490>)][]
>
> > --
> > Mike Conley
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---