Hi Michael,

I have a similar (but subtly different) problem to this, trying to mix 
single- and joined-table inheritance.
Essentially my model looks as follows:

Product(Base)
PhysicalProduct(Product)       
NonPhysicalProduct(Product)

The Physical/NonPhysicalProduct use single table inheritance whilst objects 
inheriting from them use joined tables...  

I have a fully working model --- and there's no question that it works!! 
 But I can't help feeling that I've missed something relating to the 
__mapper_args__ which is then requiring explicit calls to __init__ objects 
higher up the tree.  (rather than bunging up this message, please see the 
attached file) 

I'd be really grateful if you could take a look and hopefully point me in 
the right direction.

Many thanks,
Rob 
   





On Wednesday, 17 August 2011 00:42:28 UTC+1, Michael Bayer wrote:
>
>
> On Aug 16, 2011, at 5:37 PM, Mike Gilligan wrote:
>
> I have a single table that looks similar to the following:
>
> class Equipment(Base):
>     type = Column(CHAR(1), primary_key=True)
>     sub_type = Column(CHAR(1), primary_key=True)
>     code = Column(CHAR(5), primary_key=True)
>
>
> For historical purposes, I cannot modify this table. I would like to setup 
> multi-level inheritance similar to this, however it does not work:
>
> class Equipment(Base):
>     type = Column(CHAR(1), primary_key=True)
>     sub_type = Column(CHAR(1), primary_key=True)
>     code = Column(CHAR(5), primary_key=True)
>     __mapper_args__ = {'polymorphic_on': type}
>
>
> class Vehicle(Equipment):
>      __mapper_args__ = {'polymorphic_identity': 'V', 'polymorphic_on': 
> sub_type}
>
>
> class Bus(Vehicle)
>      __mapper_args__ = {'polymorphic_identity': 'B'}
>
>
> class Rail(Vehicle)
>      __mapper_args__ = {'polymorphic_identity': 'R'}
>
>
> I can concatenate the multiple column values into a single discriminator 
> column_property but then I do not have an easy way to retrieve all 
> vehicles. Any ideas?
>
>
> The inheritance querying does handle multi-level inheritance so if your 
> discriminator was on a concatenation of both things would work just fine, 
> i.e. if you queried for Vehicle, etc.   Each object's 
> "polymorphic_identity" would need to include the concatenated value, of 
> course.
>
> Unfortunately we're just beginning to support inheritance discriminators 
> on a column_property(), and you need to use a very specific approach to 
> make this work right now.  There's some tickets in trac to allow this 
> functionality out of the box.    Attached is an example script which 
> exercises the above mapping - it uses declarative to minimize the impact of 
> the workaround.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/KzPgMan_6MIJ.
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.

"""
mixed single and joined table inheritance.
"""

from sqlalchemy import *
from sqlalchemy import types
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base,  declared_attr

Base = declarative_base()

class Product(Base):
    __tablename__ = 'products'
    id   = Column(types.Integer, primary_key=True)
    discriminator = Column('product_type', types.String(50), nullable=False)

    __mapper_args__ = {'polymorphic_on': discriminator}

    def price_history(self):
        return []


class PhysicalProduct(Product):
    p_discr = Column(types.String(50))

    @declared_attr
    def __mapper_args__(cls):
        return {'polymorphic_on': cls.p_discr,
                'polymorphic_identity' : 'physical_product'}

    def __init__(self, **kw):
        print "init PP kwargs:", kw
        self.discriminator = 'physical_product'

    def inventory(self):
        return "computed inventory"


class NonPhysicalProduct(Product):
    np_discr = Column(types.String(50))

    @declared_attr
    def __mapper_args__(cls):
        return {'polymorphic_on': cls.np_discr,
                'polymorphic_identity' : 'nonphysical_product'}

    def __init__(self, **kw):
        print "init NP kwargs:", kw
        self.discriminator = 'nonphysical_product'

    def somefunc(self):
        return "someval"


class Newspaper(PhysicalProduct):
    __tablename__ = 'newspapers'
    __mapper_args__ = {'polymorphic_identity': 'newspaper'}

    id = Column(types.Integer,
                ForeignKey('products.id'),
                primary_key=True
                )
    title = Column(types.String(50))

    def __init__(self, title):
        self.title = title
        super(Newspaper, self).__init__()


class NewspaperDelivery(NonPhysicalProduct):
    __tablename__ = 'deliveries'
    __mapper_args__ = {'polymorphic_identity': 'delivery'}

    id = Column(types.Integer,
                ForeignKey('products.id'),
                primary_key=True
                )
    destination = Column(types.String(50))

    def __init__(self, destination):
        self.destination = destination
        super(NewspaperDelivery, self).__init__()


e = create_engine('sqlite:///:memory:', echo=True)
Base.metadata.drop_all(e)
Base.metadata.create_all(e)

session = Session(e, autoflush=True, autocommit=False)

session.add_all([
    Newspaper(title="Financial Times"),
    NewspaperDelivery(destination="__somewhere__")
])


session.commit()


Reply via email to