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
-~----------~----~----~----~------~----~------~--~---

Reply via email to