__table_args__ is passed as a tuple with no dict argument.
Improved documentation. [ticket:1468]
+ - A column can be added to a joined-table subclass after
+ the class has been constructed (i.e. via class-level
+ attribute assignment). The column is added to the underlying
+ Table as always, but now the mapper will rebuild its
+ "join" to include the new column, instead of raising
+ an error about "no such column, use column_property()
+ instead". [ticket:1523]
+
- test
- Added examples into the test suite so they get exercised
regularly and cleaned up a couple deprecation warnings.
for c in columns:
mc = self.mapped_table.corresponding_column(c)
if not mc:
- raise sa_exc.ArgumentError("Column '%s' is not represented in mapper's table. "
- "Use the `column_property()` function to force this column "
- "to be mapped as a read-only attribute." % c)
+ mc = self.local_table.corresponding_column(c)
+ if mc:
+ # if the column is in the local table but not the mapped table,
+ # this corresponds to adding a column after the fact to the local table.
+ self.mapped_table._reset_exported()
+ mc = self.mapped_table.corresponding_column(c)
+ if not mc:
+ raise sa_exc.ArgumentError("Column '%s' is not represented in mapper's table. "
+ "Use the `column_property()` function to force this column "
+ "to be mapped as a read-only attribute." % c)
mapped_column.append(mc)
prop = ColumnProperty(*mapped_column)
else:
def go():
assert sess.query(Person).filter(Manager.name=='dogbert').one().id
self.assert_sql_count(testing.db, go, 1)
+
+ def test_add_subcol_after_the_fact(self):
+ class Person(Base, ComparableEntity):
+ __tablename__ = 'people'
+ id = Column('id', Integer, primary_key=True, test_needs_autoincrement=True)
+ name = Column('name', String(50))
+ discriminator = Column('type', String(50))
+ __mapper_args__ = {'polymorphic_on':discriminator}
+ class Engineer(Person):
+ __tablename__ = 'engineers'
+ __mapper_args__ = {'polymorphic_identity':'engineer'}
+ id = Column('id', Integer, ForeignKey('people.id'), primary_key=True)
+
+ Engineer.primary_language = Column('primary_language', String(50))
+
+ Base.metadata.create_all()
+
+ sess = create_session()
+ e1 = Engineer(primary_language='java', name='dilbert')
+ sess.add(e1)
+ sess.flush()
+ sess.expunge_all()
+
+ eq_(sess.query(Person).first(),
+ Engineer(primary_language='java', name='dilbert')
+ )
+
def test_subclass_mixin(self):
class Person(Base, ComparableEntity):
__tablename__ = 'people'
assert 'email_addres' not in a.__dict__
eq_(a.email_address, 'jack@bean.com')
+ @testing.resolve_artifact_names
+ def test_column_not_present(self):
+ assert_raises_message(sa.exc.ArgumentError, "not represented in mapper's table", mapper, User, users, properties={
+ 'foo':addresses.c.user_id
+ })
+
@testing.resolve_artifact_names
def test_bad_constructor(self):
"""If the construction of a mapped class fails, the instance does not get placed in the session"""