J. Cliff Dyer | 15 May 17:21
Picon
Favicon

Polymorphic across foreign key


I'm trying to implement polymorphic inheritance using the
sqlalchemy.ext.declarative, but the field that I want to use for the
polymorphic_on is not in my polymorphic base table, but at the other end
of a many-to-one relationship.  We have items of many types, and in the
item table, we have a type_id field which contains an integer, but in
the item_type table, that integer is mapped to a descriptive name.
Essentially, I'd like to use that name as my polymorphic_identity.  I've
tried to implement this with declarative classes below, but I get an
error, also shown below.

class ItemType(Declarative):
    __table__ = sa.Table('item_type', Declarative.metadata)
    type_id = sa.Column('type_id', sa.Integer, primary_key=True)
    description = sa.Column('description', sa.Unicode(250))
    item = orm.relation('Item', backref='item_type')

class Item(Declarative):
    __table__ = sa.Table('item', Declarative.metadata)
    item_id = sa.Column('item_id', sa.Integer, primary_key=True)
    type_id = sa.Column('type_id', sa.Integer,
sa.ForeignKey('item_type.type_id'))
    short_title = sa.Column('short_title', sa.Unicode(100))
    __mapper_args__ = {'polymorphic_on': ItemType.description }

### Traceback follows:

"""
Traceback (most recent call last):
  File "polymorph_test.py", line 23, in ?
(Continue reading)

J. Cliff Dyer | 15 May 17:30
Picon
Favicon

Re: Polymorphic across foreign key


On Thu, 2008-05-15 at 11:24 -0400, J. Cliff Dyer wrote:
> I'm trying to implement polymorphic inheritance using the
> sqlalchemy.ext.declarative, but the field that I want to use for the
> polymorphic_on is not in my polymorphic base table, but at the other end
> of a many-to-one relationship.  We have items of many types, and in the
> item table, we have a type_id field which contains an integer, but in
> the item_type table, that integer is mapped to a descriptive name.
> Essentially, I'd like to use that name as my polymorphic_identity.  I've
> tried to implement this with declarative classes below, but I get an
> error, also shown below.
> 
> 
> class ItemType(Declarative):
>     __table__ = sa.Table('item_type', Declarative.metadata)
>     type_id = sa.Column('type_id', sa.Integer, primary_key=True)
>     description = sa.Column('description', sa.Unicode(250))
>     item = orm.relation('Item', backref='item_type')
> 
> class Item(Declarative):
>     __table__ = sa.Table('item', Declarative.metadata)
>     item_id = sa.Column('item_id', sa.Integer, primary_key=True)
>     type_id = sa.Column('type_id', sa.Integer,
> sa.ForeignKey('item_type.type_id'))
>     short_title = sa.Column('short_title', sa.Unicode(100))
>     __mapper_args__ = {'polymorphic_on': ItemType.description }
> 
> 
> ### Traceback follows:
> 
(Continue reading)

J. Cliff Dyer | 15 May 18:12
Picon
Favicon

Re: Polymorphic across foreign key


On Thu, 2008-05-15 at 11:30 -0400, J. Cliff Dyer wrote:
> On Thu, 2008-05-15 at 11:24 -0400, J. Cliff Dyer wrote:
> > I'm trying to implement polymorphic inheritance using the
> > sqlalchemy.ext.declarative, but the field that I want to use for the
> > polymorphic_on is not in my polymorphic base table, but at the other end
> > of a many-to-one relationship.  We have items of many types, and in the
> > item table, we have a type_id field which contains an integer, but in
> > the item_type table, that integer is mapped to a descriptive name.
> > Essentially, I'd like to use that name as my polymorphic_identity.  I've
> > tried to implement this with declarative classes below, but I get an
> > error, also shown below.
> > 
> > 

OK.  The old example was wrong in other ways.  That was a problem with
__table__ vs. __tablename__, but I got past that, and got my
polymorphism working on the basic case, where I just use the type_id
directly as follows:

class ItemType(Declarative):
    __tablename__ = 'item_type'
    type_id = sa.Column('type_id', sa.Integer, primary_key=True)
    description = sa.Column('description', sa.Unicode(250))

class Item(Declarative):
    __tablename__ = 'item'
    item_id = sa.Column('item_id', sa.Integer, primary_key=True)
    type_id = sa.Column('type_id', sa.Integer,
sa.ForeignKey('item_type.type_id'))
(Continue reading)

Michael Bayer | 15 May 18:27

Re: Polymorphic across foreign key


On May 15, 2008, at 12:12 PM, J. Cliff Dyer wrote:

>
>
> How can I use this field for polymorphism?  Is it possible?

polymorphic discriminators are currently table-local scalar columns.   
So if you had a many-to-one of discriminators, youd currently have to  
encode the discriminator to the primary key identifier of each  
discriminotor.  We will eventually allow a python function to be used  
as a discriminator as well which you can use to add a level of  
abstraction to this (you'd preload the list of discriminiator objects  
and again map based on primary key).

But a straight load of an entity relying upon an inline JOIN to get  
the polymorphic discriminator in all cases, automatically by SA, is  
not going to happen - its inefficient and would be very complex to  
implement.

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To post to this group, send email to sqlalchemy <at> googlegroups.com
To unsubscribe from this group, send email to sqlalchemy-unsubscribe <at> googlegroups.com
For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

J. Cliff Dyer | 15 May 20:44
Picon
Favicon

Re: Polymorphic across foreign key


On Thu, 2008-05-15 at 12:27 -0400, Michael Bayer wrote:
> 
> On May 15, 2008, at 12:12 PM, J. Cliff Dyer wrote:
> 
> >
> >
> > How can I use this field for polymorphism?  Is it possible?
> 
> 
> polymorphic discriminators are currently table-local scalar columns.   
> So if you had a many-to-one of discriminators, youd currently have to  
> encode the discriminator to the primary key identifier of each  
> discriminotor.  We will eventually allow a python function to be used  
> as a discriminator as well which you can use to add a level of  
> abstraction to this (you'd preload the list of discriminiator objects  
> and again map based on primary key).
> 
> But a straight load of an entity relying upon an inline JOIN to get  
> the polymorphic discriminator in all cases, automatically by SA, is  
> not going to happen - its inefficient and would be very complex to  
> implement.
> 

Thanks.  That makes sense.  I guess if you can pull across a foreign
key, you can pull across any arbitrary query.  

My goal was to have the code self-documenting in this respect, and I've
achieved that by creating a helper function get_type_id(type_name), so
each polymorphic child of Item now has 
(Continue reading)


Gmane