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 [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.
>
--
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.