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.