what version of SQLA is that ? I cannot reproduce. test case: from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base, declared_attr, has_inherited_table
Base= declarative_base() class Person(Base): id = Column(Integer, primary_key=True) type = Column('type', String(50)) @declared_attr def __tablename__(cls): if has_inherited_table(cls): return None return cls.__name__.lower() @declared_attr def __mapper_args__(cls): if cls.__name__ == 'Person': mapper_args = {} mapper_args['polymorphic_on'] = cls.type return mapper_args else: return {"polymorphic_identity": cls.__name__} class Mixin(object): @declared_attr def target_id(cls): return Column('target_id', ForeignKey('target.id')) @declared_attr def target(cls): return relationship("Target") class Engineer(Person, Mixin): pass class Target(Base): __tablename__ = 'target' id = Column(Integer, primary_key=True) configure_mappers() e = create_engine("sqlite://", echo=True) Base.metadata.create_all(e) s = Session(e) s.add_all([ Engineer(), Engineer(target=Target()) ]) print s.query(Engineer, Target).outerjoin(Engineer.target).all() output: 2012-04-16 10:34:51,368 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) 2012-04-16 10:34:51,369 INFO sqlalchemy.engine.base.Engine INSERT INTO target DEFAULT VALUES 2012-04-16 10:34:51,369 INFO sqlalchemy.engine.base.Engine () 2012-04-16 10:34:51,369 INFO sqlalchemy.engine.base.Engine INSERT INTO person (type, target_id) VALUES (?, ?) 2012-04-16 10:34:51,370 INFO sqlalchemy.engine.base.Engine ('Engineer', None) 2012-04-16 10:34:51,370 INFO sqlalchemy.engine.base.Engine INSERT INTO person (type, target_id) VALUES (?, ?) 2012-04-16 10:34:51,370 INFO sqlalchemy.engine.base.Engine ('Engineer', 1) 2012-04-16 10:34:51,371 INFO sqlalchemy.engine.base.Engine SELECT person.id AS person_id, person.type AS person_type, person.target_id AS person_target_id, target.id AS target_id FROM person LEFT OUTER JOIN target ON target.id = person.target_id WHERE person.type IN (?) 2012-04-16 10:34:51,371 INFO sqlalchemy.engine.base.Engine ('Engineer',) [(<__main__.Engineer object at 0x1014ff090>, None), (<__main__.Engineer object at 0x1014ffa10>, <__main__.Target object at 0x1014ffed0>)] On Apr 16, 2012, at 12:17 AM, Amos wrote: > I am attempting to use STI with mixins on the derived/inheriting > classes. If the mixin has a simple Column, everything works great. But > when I have a ForeignKey on the Column, and therefore use the > `declared_attr` decorator, I get an exception when I attempt to query > the child collection. > > For the example below, querying the Engineer class throws the > following exception: > > InvalidRequestError: Class <class 'Person'> does not have a mapped > column named 'target_id' > > Here's some code: > > class Person(Base): > id = Column(Integer, primary_key=True) > type = Column('type', String(50)) > > @declared_attr > def __tablename__(cls): > if has_inherited_table(cls): > return None > return cls.__name__.lower() > > @declared_attr > def __mapper_args__(cls): > if cls.__name__ == 'Person': > mapper_args = {} > mapper_args['polymorphic_on'] = cls.type > return mapper_args > else: > return {"polymorphic_identity": cls.__name__} > > class Mixin(object): > simple_column = Column(Integer, nullable=True) # This column > is mapped correctly > > @declared_attr > def target_id(cls): # But when I have a column with a > ForeignKey, and I used `declared_attr` - everything breaks down > return Column('target_id', ForeignKey('target.id')) > > @declared_attr > def target(cls): # Relationships also work correctly, if > target_id is defined in the Person class > return relationship("Target") > > class Engineer(Person, Mixin): > pass > > I know I can get around this by declaring the target_id on the Person > class but then I lose the encapsulation provided by the Mixin class. > Why does declaring a simple Column on the Mixin work perfectly, but > fail when declaring a column using the `declared_attr` decorator? > > -- > 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.