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 [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.
"""
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()