funny, that's absolutely a bug and it works in declarative because the same fix you have there was already applied some time ago within declarative. this is #2153 targeted at 0.6.8 so I will get to it when i make a pass through a set of small 0.6.8 issues later in the week.
On Apr 28, 2011, at 10:40 AM, Torsten Landschoff wrote: > Hello world! > > I am currently trying to transform my code from classic (schema defined in an > extra python module) to declarative. As intermediate step I am moving the > table definitions to the class implementations. > > What I am running into is sketched in the following example. In reality, I > have different modules for Base, Derived and Owner. > > ------- > from sqlalchemy import * > from sqlalchemy.orm import * > > metadata = MetaData() > > class Base(object): pass > > base_table = Table("base", metadata, > Column("id", Integer, primary_key=True), > Column("target_type", String)) > > mapper(Base, base_table, polymorphic_on=base_table.c.target_type) > > > class Derived(Base): pass > > derived_table = Table("derived", metadata, > Column("id", Integer, ForeignKey("base.id"), primary_key=True), > Column("owner_id", Integer, ForeignKey("owner.owner_id"), nullable=False)) > > mapper(Derived, derived_table, polymorphic_identity="derived", inherits=Base) > > > class Owner(object): pass > > owner_table = Table("owner", metadata, > Column("owner_id", Integer, primary_key=True)) > > mapper(Owner, owner_table) > ------- > > Running this gives me the following exception: > > Traceback (most recent call last): > File "inherit_problem.py", line 21, in <module> > mapper(Derived, derived_table, polymorphic_identity="derived", > inherits=Base) > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/orm/__init__.py", > line 890, in mapper > return Mapper(class_, local_table, *args, **params) > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/orm/mapper.py", > line 208, in __init__ > self._configure_inheritance() > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/orm/mapper.py", > line 259, in _configure_inheritance > self.local_table) > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/sql/util.py", > line 227, in join_condition > col = fk.get_referent(left) > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/schema.py", > line 1161, in get_referent > return table.corresponding_column(self.column) > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/util.py", > line 1517, in __get__ > obj.__dict__[self.__name__] = result = self.fget(obj) > File > "/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.8dev-py2.6.egg/sqlalchemy/schema.py", > line 1223, in column > "foreign key to target column '%s'" % (self.parent, tname, colname)) > sqlalchemy.exc.NoReferencedTableError: Foreign key assocated with column > 'derived.owner_id' could not find table 'owner' with which to generate a > foreign key to target column 'owner_id' > > The solution is of course to define all the tables first and do the mapping > only after that. This would put me back to point one. > > > I tried to get around this by patching SA with this patch: > > ------- > diff -r 27fec7a0e05f lib/sqlalchemy/orm/mapper.py > --- a/lib/sqlalchemy/orm/mapper.py Wed Apr 27 12:51:50 2011 -0400 > +++ b/lib/sqlalchemy/orm/mapper.py Thu Apr 28 16:26:57 2011 +0200 > @@ -256,7 +256,8 @@ > # want (allows test/inheritance.InheritTest4 to pass) > self.inherit_condition = sqlutil.join_condition( > > self.inherits.local_table, > - self.local_table) > + self.local_table, > + > ignore_nonexistent_tables=True) > self.mapped_table = sql.join( > self.inherits.mapped_table, > self.local_table, > ------- > > This makes the example work, but I'd rather stay with an official SQLAlchemy. > So would it be possible to make this work out of the box? Is there a better > way to implement this? > > Any hints are greatly appreciated. > > Torsten > > PS: I just tried to implement this in a declarative way. This seems to work > fine: > > ------- > from sqlalchemy import * > from sqlalchemy.orm import * > from sqlalchemy.ext.declarative import declarative_base > > DeclBase = declarative_base() > > class Base(DeclBase): > __tablename__ = "base" > id = Column(Integer, primary_key=True) > target_type = Column(String) > > __mapper_args__ = { "polymorphic_on": target_type } > > > class Derived(Base): > __tablename__ = "derived" > id = Column(Integer, ForeignKey(Base.id), primary_key=True) > owner_id = Column(Integer, ForeignKey("owner.owner_id"), nullable=False) > owner = relationship("Owner") > > __mapper_args__ = { "polymorphic_identity": "derived" } > > > class Owner(DeclBase): > __tablename__ = "owner" > owner_id = Column(Integer, primary_key=True) > > engine = create_engine("sqlite:///:memory:", echo=True) > DeclBase.metadata.create_all(engine) > session = sessionmaker(engine)() > > owner = Owner() > derived = Derived(owner=owner) > session.add(derived) > session.commit() > ------- > > However, I already failed to do the whole conversion in one giant commit, > therefore I would prefer to do it in small steps. > > -- > DYNAmore Gesellschaft fuer Ingenieurdienstleistungen mbH > Torsten Landschoff > > Office Dresden > Tel: +49-(0)351-4519587 > Fax: +49-(0)351-4519561 > > mailto:torsten.landsch...@dynamore.de > http://www.dynamore.de > > Registration court: Mannheim, HRB: 109659, based in Karlsruhe, > Managing director: Prof. Dr. K. Schweizerhof, Dipl.-Math. U. Franz > > -- > 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. -- 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.