<p dir="auto"><strong>Migrated issue, originally created by Michael Bayer (<a href="https://github.com/zzzeek">@zzzeek</a>)</strong></p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from sqlalchemy import Integer, Column, ForeignKey
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)


class AAbs(A):
    __abstract__ = True


class B1(A):
    __tablename__ = 'b1'
    id = Column(ForeignKey('a.id'), primary_key=True)


class B2(AAbs):
    __tablename__ = 'b2'
    id = Column(ForeignKey('a.id'), primary_key=True)


assert B1.__mapper__.inherits is A.__mapper__  # passes

assert B2.__mapper__.inherits is A.__mapper__  # fails
"><pre class="notranslate"><code class="notranslate">from sqlalchemy import Integer, Column, ForeignKey
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class A(Base):
    __tablename__ = 'a'
    id = Column(Integer, primary_key=True)


class AAbs(A):
    __abstract__ = True


class B1(A):
    __tablename__ = 'b1'
    id = Column(ForeignKey('a.id'), primary_key=True)


class B2(AAbs):
    __tablename__ = 'b2'
    id = Column(ForeignKey('a.id'), primary_key=True)


assert B1.__mapper__.inherits is A.__mapper__  # passes

assert B2.__mapper__.inherits is A.__mapper__  # fails

</code></pre></div>
<p dir="auto"><strong>Migrated issue, originally created by David Lord (<a href="https://github.com/davidism">@davidism</a>)</strong></p>
<p dir="auto">I have the following models:</p>
<ul dir="auto">
<li><code class="notranslate">Device</code></li>
<li><code class="notranslate">DeviceSource</code> has a foreign key and relationship to <code class="notranslate">Device</code></li>
<li><code class="notranslate">LDAPDeviceSource</code> is a joined-table inheritance of <code class="notranslate">DeviceSource</code></li>
</ul>
<p dir="auto">In order to make defining new <code class="notranslate">DeviceSource</code> subclasses easier, I created <code class="notranslate">DeviceSourceMixin</code>, which inherits from <code class="notranslate">DeviceSource</code> and provides declared attrs for <code class="notranslate">__tablename__</code> and the foreign primary <code class="notranslate">id</code>.  <code class="notranslate">DeviceSourceMixin</code> is <code class="notranslate">__abstract__</code> so that it doesn't create a table of its own.</p>
<p dir="auto">The issue is that this intermediate <code class="notranslate">__abstract__</code> seems to break the declarative model.  The foreign key and relationship in <code class="notranslate">DeviceSource</code> do not get inherited by <code class="notranslate">LDAPDeviceSource</code> when subclassing <code class="notranslate">DeviceSourceMixin</code>.</p>
<p dir="auto">This code demonstrates the issue:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import sqlalchemy as sa
from sqlalchemy.ext.declarative import declared_attr, as_declarative
from sqlalchemy.orm import Session, relationship

engine = sa.create_engine('sqlite:///:memory:', echo=True)
session = Session(bind=engine)


@as_declarative(bind=engine)
class Base(object):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    id = sa.Column(sa.Integer, primary_key=True)


class Device(Base):
    pass


class DeviceSource(Base):
    type = sa.Column(sa.String, nullable=False)
    device_id = sa.Column(sa.Integer, sa.ForeignKey(Device.id), nullable=False)

    device = relationship(Device, backref='sources')

    __mapper_args__ = {
        'polymorphic_on': type
    }


class DeviceSourceMixin(DeviceSource):
    __abstract__ = True

    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    @declared_attr
    def id(cls):
        return sa.Column(sa.Integer, sa.ForeignKey(DeviceSource.id), primary_key=True)


class LDAPDeviceSource(DeviceSourceMixin):
    name = sa.Column(sa.String, nullable=False)

    __mapper_args__ = {
        'polymorphic_identity': 'ldap'
    }


Base.metadata.create_all()
d1 = Device()
s1 = LDAPDeviceSource(device=d1, name='s1')
session.add(s1)
session.commit()"><pre class="notranslate"><code class="notranslate">import sqlalchemy as sa
from sqlalchemy.ext.declarative import declared_attr, as_declarative
from sqlalchemy.orm import Session, relationship

engine = sa.create_engine('sqlite:///:memory:', echo=True)
session = Session(bind=engine)


@as_declarative(bind=engine)
class Base(object):
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    id = sa.Column(sa.Integer, primary_key=True)


class Device(Base):
    pass


class DeviceSource(Base):
    type = sa.Column(sa.String, nullable=False)
    device_id = sa.Column(sa.Integer, sa.ForeignKey(Device.id), nullable=False)

    device = relationship(Device, backref='sources')

    __mapper_args__ = {
        'polymorphic_on': type
    }


class DeviceSourceMixin(DeviceSource):
    __abstract__ = True

    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()

    @declared_attr
    def id(cls):
        return sa.Column(sa.Integer, sa.ForeignKey(DeviceSource.id), primary_key=True)


class LDAPDeviceSource(DeviceSourceMixin):
    name = sa.Column(sa.String, nullable=False)

    __mapper_args__ = {
        'polymorphic_identity': 'ldap'
    }


Base.metadata.create_all()
d1 = Device()
s1 = LDAPDeviceSource(device=d1, name='s1')
session.add(s1)
session.commit()
</code></pre></div>
<p dir="auto">It produces the following error:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Traceback (most recent call last):
  File &quot;/home/david/Projects/cedar/example2.py&quot;, line 62, in &lt;module&gt;
    s1 = LDAPDeviceSource(device=d1, name='s1')
  File &quot;&lt;string&gt;&quot;, line 4, in __init__
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/state.py&quot;, line 260, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File &quot;&lt;string&gt;&quot;, line 6, in __init__
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/ext/declarative/base.py&quot;, line 526, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 226, in __set__
    instance_dict(instance), value, None)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 812, in set
    value = self.fire_replace_event(state, dict_, value, old, initiator)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 832, in fire_replace_event
    state, value, previous, initiator or self._replace_token)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 1148, in emit_backref_from_scalar_set_event
    passive=PASSIVE_NO_FETCH)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 980, in append
    collection.append_with_event(value, initiator)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py&quot;, line 653, in append_with_event
    self._data()._sa_appender(item, _sa_initiator=initiator)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py&quot;, line 1047, in append
    item = __set(self, item, _sa_initiator)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py&quot;, line 1019, in __set
    item = executor.fire_append_event(item, _sa_initiator)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py&quot;, line 716, in fire_append_event
    item, initiator)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 929, in fire_append_event
    value = fn(state, value, initiator or self._append_token)
  File &quot;/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py&quot;, line 1157, in emit_backref_from_collection_append_event
    child_impl = child_state.manager[key].impl
KeyError: 'device'"><pre class="notranslate"><code class="notranslate">Traceback (most recent call last):
  File "/home/david/Projects/cedar/example2.py", line 62, in &lt;module&gt;
    s1 = LDAPDeviceSource(device=d1, name='s1')
  File "&lt;string&gt;", line 4, in __init__
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/state.py", line 260, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "&lt;string&gt;", line 6, in __init__
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/ext/declarative/base.py", line 526, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 226, in __set__
    instance_dict(instance), value, None)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 812, in set
    value = self.fire_replace_event(state, dict_, value, old, initiator)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 832, in fire_replace_event
    state, value, previous, initiator or self._replace_token)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 1148, in emit_backref_from_scalar_set_event
    passive=PASSIVE_NO_FETCH)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 980, in append
    collection.append_with_event(value, initiator)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py", line 653, in append_with_event
    self._data()._sa_appender(item, _sa_initiator=initiator)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py", line 1047, in append
    item = __set(self, item, _sa_initiator)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py", line 1019, in __set
    item = executor.fire_append_event(item, _sa_initiator)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/collections.py", line 716, in fire_append_event
    item, initiator)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 929, in fire_append_event
    value = fn(state, value, initiator or self._append_token)
  File "/home/david/.virtualenvs/cedar/lib/python3.4/site-packages/sqlalchemy/orm/attributes.py", line 1157, in emit_backref_from_collection_append_event
    child_impl = child_state.manager[key].impl
KeyError: 'device'
</code></pre></div>