simplify polymorphic_on assignment

Issue #1895 resolved
Mike Bayer repo owner created an issue

attached patch moves 'polymorphic_on' assignment to be via attribute setting. All tests continue to pass. The advantages here include:

  • the polymorphic_identity is ready immediately on an instance
  • the polymorphic attribute is a regular attribute and can be set or changed
  • less work in _save_obj - the attribute doesn't need to be expired, don't need to compare table columns to polymorphic_on
  • double attributes can be set (see test below).

    #!python from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base

    Base = declarative_base()

    class AbstractA(Base):

    tablename = "abstract_a"

    id = Column(Integer, primary_key=True) class_name = Column('class_name', String(50))

    mapper_args = { 'polymorphic_on': class_name, }

    class AbstractB(AbstractA):

    tablename = "abstract_b"

    id = Column(Integer, ForeignKey('abstract_a.id'), primary_key=True) class_name = Column('class_name', String(50))

    mapper_args = { 'polymorphic_on': class_name, 'polymorphic_identity': tablename, }

    class ClassA(AbstractB):

    tablename = "table_a" mapper_args = { 'polymorphic_identity': tablename, }

    id = Column(Integer, ForeignKey('abstract_b.id'),primary_key=True) label = Column('label', String(50))

    def init(self, label): self.label = label

    compile_mappers()

    e = create_engine('sqlite://', echo=True) Base.metadata.create_all(e)

    sess = Session(e)

    c1 = ClassA('toto') sess.add(c1) sess.flush() assert c1.class_name == 'table_a'

    sess.commit()

    assert isinstance(sess.query(AbstractB).first(), ClassA)

    sess.close()

    assert isinstance(sess.query(AbstractA).first(), ClassA)

tests include that polymorphic_identity is set up on class as its created immediately.

Comments (2)

  1. Log in to comment