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 <[email protected]>
>
> 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 [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.
>
>
>
> --
> 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.