Hey everyone, I *think* this is a limitation of having classes that are polymorphic_on a join (instead of mapping a join), but I'm going to ask anyway to make sure I understand.
I have a hierarchy of mappers to represent various network interfaces
on various devices. This is polymorphic_on a join to the
discriminator of the assocated device records:
-----
iftype_join = select([device_t.c.model],
from_obj=[interface_t.join(device_t)]).alias()
interface_m = orm.mapper(InterfaceBase, interface_t,
polymorphic_on=iftype_join.c.model,
polymorphic_identity=0,
properties={"device": orm.relation(Device),
"binding": orm.relation(Binding)})
switchport_m = orm.mapper(SwitchPort, inherits=interface_m,
polymorphic_identity=1)
ciscoswitchport_m = orm.mapper(CiscoSwitchPort, inherits=switchport_m,
polymorphic_identity=2)
juniperswitchport_m = orm.mapper(JuniperSwitchPort, inherits=switchport_m,
polymorphic_identity=3)
routerport_m = orm.mapper(RouterPort, inherits=interface_m,
polymorphic_identity=4)
ciscorouterport_m = orm.mapper(CiscoRouterPort, inherits=routerport_m,
polymorphic_identity=5)
juniperrouterport_m = orm.mapper(JuniperRouterPort, inherits=routerport_m,
polymorphic_identity=6)
-----
Next, a binding ties together groups of router and switch ports:
-----
binding_m = orm.mapper(Binding, binding_t,
properties={'routerports': orm.relation(RouterPort),
'switchports': orm.relation(SwitchPort)})
-----
But, when I access these members, the collections aren't restricted to
the appropriate subclasses RouterPort/SwitchPort. They include all
interface types:
>>> print [type(x) for x in b1.routerports]
[<class '__main__.CiscoRouterPort'>, <class '__main__.CiscoSwitchPort'>]
Here's the generated SQL:
2010-08-11 10:29:42,560 INFO sqlalchemy.engine.base.Engine.0x...60ec BEGIN
2010-08-11 10:29:42,561 INFO sqlalchemy.engine.base.Engine.0x...60ec SELECT
binding.id AS binding_id
FROM binding
WHERE binding.id = ?
2010-08-11 10:29:42,561 INFO sqlalchemy.engine.base.Engine.0x...60ec [1]
2010-08-11 10:29:42,561 INFO sqlalchemy.engine.base.Engine.0x...60ec SELECT
interface.id AS interface_id, interface.deviceid AS interface_deviceid,
interface.bindingid AS interface_bindingid
FROM interface
WHERE ? = interface.bindingid
2010-08-11 10:29:42,561 INFO sqlalchemy.engine.base.Engine.0x...60ec [1]
Is this a limitation of being polymorphic_on a join instead of mapping
the join?
Thanks,
Ross
from sqlalchemy import *
import sqlalchemy.orm as orm
class Device(object):
pass
class Switch(Device):
pass
class CiscoSwitch(Switch):
pass
class JuniperSwitch(Switch):
pass
class Router(Device):
pass
class CiscoRouter(Router):
pass
class JuniperRouter(Router):
pass
class InterfaceBase(object):
pass
class SwitchPort(InterfaceBase):
pass
class CiscoSwitchPort(SwitchPort):
pass
class JuniperSwitchPort(SwitchPort):
pass
class RouterPort(InterfaceBase):
pass
class CiscoRouterPort(RouterPort):
pass
class JuniperRouterPort(RouterPort):
pass
class Binding(object):
pass
engine = create_engine('sqlite:///:memory:')
metadata = MetaData()
device_t = Table('device', metadata,
Column('id', Integer, primary_key=True),
Column('model', Integer))
interface_t = Table('interface', metadata,
Column('id', Integer, primary_key=True),
Column('deviceid', Integer,
ForeignKey('device.id')),
Column('bindingid', Integer,
ForeignKey('binding.id')))
binding_t = Table('binding', metadata,
Column('id', Integer, primary_key=True))
metadata.create_all(engine)
device_m = orm.mapper(Device, device_t,
polymorphic_on=device_t.c.model,
polymorphic_identity=0)
switch_m = orm.mapper(Switch, inherits=device_m,
polymorphic_identity=1)
ciscoswitch_m = orm.mapper(CiscoSwitch, inherits=switch_m,
polymorphic_identity=2)
juniperswitch_m = orm.mapper(JuniperSwitch, inherits=switch_m,
polymorphic_identity=3)
router_m = orm.mapper(Router, inherits=device_m,
polymorphic_identity=4)
ciscorouter_m = orm.mapper(CiscoRouter, inherits=router_m,
polymorphic_identity=5)
juniperrouter_m = orm.mapper(JuniperRouter, inherits=router_m,
polymorphic_identity=6)
iftype_join = select([device_t.c.model],
from_obj=[interface_t.join(device_t)]).alias()
interface_m = orm.mapper(InterfaceBase, interface_t,
polymorphic_on=iftype_join.c.model,
polymorphic_identity=0,
properties={"device": orm.relation(Device),
"binding":
orm.relation(Binding)})
switchport_m = orm.mapper(SwitchPort, inherits=interface_m,
polymorphic_identity=1)
ciscoswitchport_m = orm.mapper(CiscoSwitchPort, inherits=switchport_m,
polymorphic_identity=2)
juniperswitchport_m = orm.mapper(JuniperSwitchPort,
inherits=switchport_m,
polymorphic_identity=3)
routerport_m = orm.mapper(RouterPort, inherits=interface_m,
polymorphic_identity=4)
ciscorouterport_m = orm.mapper(CiscoRouterPort, inherits=routerport_m,
polymorphic_identity=5)
juniperrouterport_m = orm.mapper(JuniperRouterPort,
inherits=routerport_m,
polymorphic_identity=6)
binding_m = orm.mapper(Binding, binding_t,
properties={'routerports':
orm.relation(RouterPort),
'switchports':
orm.relation(SwitchPort)})
Session = orm.sessionmaker(bind=engine)
session = Session()
b1 = Binding()
b2 = Binding()
r1 = CiscoRouter()
rp1 = CiscoRouterPort()
rp1.device = r1
rp1.binding = b1
r2 = JuniperRouter()
rp2 = JuniperRouterPort()
rp2.device = r2
rp2.binding = b2
s1 = CiscoSwitch()
sp1 = CiscoSwitchPort()
sp1.device = s1
sp1.binding = b1
s2 = JuniperSwitch()
sp2 = JuniperSwitchPort()
sp2.device = s2
sp2.binding = b2
session.add_all([r1, rp1, r2, rp2, s1, sp1, s2, sp2, b1, b2])
session.flush()
session.commit()
engine.echo = True
print [type(x) for x in b1.routerports]
print [type(x) for x in b1.switchports]
print [type(x) for x in b2.routerports]
print [type(x) for x in b2.switchports]
--
Ross Vandegrift
[email protected]
"If the fight gets hot, the songs get hotter. If the going gets tough,
the songs get tougher."
--Woody Guthrie
signature.asc
Description: Digital signature
