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/-/qNSg1VvOrWwJ.
> 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.
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base, declared_attr
Base = declarative_base()
class Equipment(Base):
__tablename__ = 'equipment'
type = Column(CHAR(1), primary_key=True)
sub_type = Column(CHAR(1), primary_key=True)
code = Column(CHAR(5), primary_key=True)
_concat_type_col = type + "|" + sub_type
concat_type = column_property(_concat_type_col)
@declared_attr
def __mapper_args__(cls):
# note that the "polymorphic_on" argument must be
# explicit with all subclass mappers as well, as currently
# a column_property()-based polymorphic_on is not propagated
# to single-table inh subclasses. An interim patch
# in ticket #2227 fixes this but ticket #2238 seeks to
# address this more generally
return {
'polymorphic_on': cls._concat_type_col,
'polymorphic_identity' : cls.cls_type + "|" + cls.cls_sub_type}
cls_type = 'equip'
cls_sub_type = ''
def __init__(self, code):
self.type = self.cls_type
self.sub_type = self.cls_sub_type
self.code = code
class Vehicle(Equipment):
cls_sub_type = 'V'
class Bus(Vehicle):
cls_sub_type = 'B'
class Rail(Vehicle):
cls_sub_type = 'R'
e = create_engine('sqlite://', echo=True)
Base.metadata.create_all(e)
s = Session(e)
s.add_all([
Bus(code='bus'),
Rail(code='rail'),
Vehicle(code='veh'),
Equipment(code='equip')
])
s.commit()
assert set(e.__class__ for e in s.query(Vehicle)) == set([Vehicle, Bus, Rail])
assert set(e.__class__ for e in s.query(Equipment)) == set([Equipment, Vehicle, Bus, Rail])
assert set(e.__class__ for e in s.query(Rail)) == set([Rail])