Default class for SQLAlchemy single table inheritance
- by eclaird
I've set up a single table inheritance, but I need a "default" class to use when
an unknown polymorphic identity is encountered. The database is not in my
control and so the data can be pretty much anything.
A working example setup:
import sqlalchemy as sa
from sqlalchemy import orm
engine = sa.create_engine('sqlite://')
metadata = sa.MetaData(bind=engine)
table = sa.Table('example_types', metadata,
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('type', sa.Integer),
)
metadata.create_all()
class BaseType(object):
pass
class TypeA(BaseType):
pass
class TypeB(BaseType):
pass
base_mapper = orm.mapper(BaseType, table,
polymorphic_on=table.c.type,
polymorphic_identity=None,
)
orm.mapper(TypeA,
inherits=base_mapper,
polymorphic_identity='A',
)
orm.mapper(TypeB,
inherits=base_mapper,
polymorphic_identity='B',
)
Session = orm.sessionmaker(autocommit=False, autoflush=False)
session = Session()
Now, if I insert a new unmapped identity...
engine.execute('INSERT INTO EXAMPLE_TYPES (TYPE) VALUES (\'C\')')
session.query(BaseType).first()
...things break.
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/query.py", line 1619, in first
ret = list(self[0:1])
File ".../SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/query.py", line 1528, in __getitem__
return list(res)
File ".../SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/query.py", line 1797, in instances
rows = [process[0](row, None) for row in fetch]
File ".../SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/mapper.py", line 2179, in _instance
_instance = polymorphic_instances[discriminator]
File ".../SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/util.py", line 83, in __missing__
self[key] = val = self.creator(key)
File ".../SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/orm/mapper.py", line 2341, in configure_subclass_mapper
discriminator)
AssertionError: No such polymorphic_identity u'C' is defined
What I expected:
>>> result = session.query(BaseType).first()
>>> result
<BaseType object at 0x1c8db70>
>>> result.type
u'C'
I think this used to work with some older version of SQLAlchemy, but I haven't
been keeping up with the development lately. Any pointers on how to accomplish
this?