On Aug 16, 2010, at 4:20 AM, jean-philippe serafin wrote: > AbstractA is AbstractB "base" class......... > AbstractB is ClassA "base" class............ > > Everything work fine in this case. > > I just want to set 'polymorphic_identity' on each inheritance level > if I set by hand : update abstract_a set class_name = 'class_a' : > AbstractA.query.first() give me back a ClassA object
The reason you can't easily set "class_name" on the base is that you've named the attribute the same thing on both AbstractA and AbstractB. So AbstractB.class_name will never affect the basemost attribute on AbstractA. If you name them differently, your constructor can ensure they are set: def __init__(self, label): self.label = label self.class_name_a = self.class_name_b = self.__tablename__ But what works better, merge them on AbstractB (still remove the unnecessary polymorphic_on from B, however), the value gets propagated to that of AbstractB: class AbstractA(Base): __tablename__ = "abstract_a" id = Column(Integer, primary_key=True) class_name = Column('class_name', String(50)) __mapper_args__ = { 'polymorphic_on': class_name, } class AbstractB(AbstractA): __tablename__ = "abstract_b" id = Column(Integer, ForeignKey('abstract_a.id'),primary_key=True) class_name = column_property(Column('class_name', String(50)), AbstractA.__table__.c.class_name) __mapper_args__ = { 'polymorphic_identity': __tablename__, } Note however, it is not possible to load a ClassA object without querying at the very least "abstract_a". So the "class_name" column of "abstract_a" is always available with regular polymorphic querying. Its redundant and less normalized to have "class_name" on both tables with the same value (technically its not normalized in the first place to have a discriminator column at all, though it has a dramatically positive effect on our ability to locate subtypes without many outer joins). So there's no reason I can think of why you'd want class_name on B. But even if you did, there's still no reason to ever put polymorphic_on on a non-base table with the current implementation, and that should still be changed to emit a warning (#1880)- even here it would have alerted you to the issue. > > > 2010/8/15 Michael Bayer <mike...@zzzcomputing.com> > > On Aug 15, 2010, at 6:52 AM, jean-philippe serafin wrote: > > > Hi, > > > > I've got a class mapping with two polymorphic inheritance : > > > > class AbstractA(Base): > > > > __tablename__ = "abstract_a" > > > > id = Column(Integer, primary_key=True) > > class_name = Column('class_name', String(50)) > > > > __mapper_args__ = { > > 'polymorphic_on': class_name, > > } > > #some stuff here > > > > class AbstractB(AbstractA): > > > > __tablename__ = "abstract_b" > > > > id = Column(Integer, ForeignKey('abstract_a.id'), > > primary_key=True) > > class_name = Column('class_name', String(50)) > > > > __mapper_args__ = { > > 'polymorphic_on': class_name, > > 'polymorphic_identity': __tablename__, > > } > > #some stuff here > > > > class ClassA(AbstractB): > > > > __tablename__ = "table_a" > > __mapper_args__ = { > > 'polymorphic_identity': __tablename__, > > } > > > > id = Column(Integer, ForeignKey('abstract_b.id'), > > primary_key=True) > > label = Column('label', String(50)) > > > > def __init__(self, label): > > self.label = label > > > > I persist a ClassA object : > > > > object = ClassA('toto') > > db_session.add(object) > > db_session.commit() > > > > When I try to reload the object like this : > > > > reloaded_object = AbstractB.query.first() > > > > I get back a ClassA object (just fine) > > > > but when I try to reload like this : > > > > reloaded_object = AbstractA.query.first() > > > > I get back a AbstractA object because abstract_a.class_name has not > > been set to polymorphic_identity. > > > > Is this an issue or expected work? > > polymorphic_on only goes on the base class. SQLA should be changed to > raise an error on the setup you have above. > > > > > > -- > > You received this message because you are subscribed to the Google Groups > > "sqlalchemy" group. > > To post to this group, send email to sqlalch...@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 sqlalch...@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 sqlalch...@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 sqlalch...@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.