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.

Reply via email to