0

I have many tables with identical columns. The difference is the table names themselves. I want to set up a inheritance chain to minimize code duplication. The following single layer inheritance works the way I want it to:

from sqlalchemy import Column, Integer, Text
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy.orm import sessionmaker

engine = sqlalchemy.create_engine('sqlite:///monDom5.db')


class Base(object):
    """base for all table classes"""
    __abstract__ = True
    __table_args__ = {'autoload': True, 'autoload_with': engine}
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()


Base = declarative_base(cls=Base)


class TransMap_HgmIntronVector(Base):
    AlignmentId = Column(Text, primary_key=True)

But requires me to specify the AlignmentId column for every instance of the Hgm base. I would instead like to do this, but get a sqlalchemy.exc.InvalidRequestError when I try to actually use it:

from sqlalchemy import Column, Integer, Text
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy.orm import sessionmaker

engine = sqlalchemy.create_engine('sqlite:///monDom5.db')

class Base(object):
    """base for all table classes"""
    __abstract__ = True
    __table_args__ = {'autoload': True, 'autoload_with': engine}
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()


# model for all Hgm tables

class Hgm(Base):
    __abstract__ = True
    AlignmentId = Column(Text, primary_key=True)


Base = declarative_base(cls=Hgm)

class TransMap_HgmIntronVector(Hgm):
    pass



metadata = Base.metadata
Session = sessionmaker(bind=engine)
session = Session()

Leads to the error

>>> metadata = Base.metadata
>>> Session = sessionmaker(bind=engine)
>>> session = Session()
>>> session.query(TransMap_HgmIntronVector).all()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 1260, in query
    return self._query_cls(entities, self, **kwargs)
  File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 110, in __init__
    self._set_entities(entities)
  File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 118, in _set_entities
    entity_wrapper(self, ent)
  File "/cluster/home/ifiddes/anaconda2/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 3829, in __init__
    "expected - got '%r'" % (column, )
sqlalchemy.exc.InvalidRequestError: SQL expression, column, or mapped entity expected - got '<class '__main__.TransMap_HgmIntronVector'>'
2
  • Are you actually planning to use sqlite? Or another database (some support different types of inheritance)? Commented Sep 23, 2016 at 17:38
  • The database is actually sqlite. Commented Sep 23, 2016 at 17:43

1 Answer 1

1

An example is in the docs. In particular, __abstract__ = True is not necessary. This works fine:

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

class Hgm(Base):
    AlignmentId = Column(Text, primary_key=True)

Base = declarative_base(cls=Hgm)

class TransMap_HgmIntronVector(Base):
    pass

Note that it may be simpler to just use a mixin for the identical columns instead.

Sign up to request clarification or add additional context in comments.

2 Comments

None of the examples in the docs fix this problem, as far as I can tell. Removing __abstract__ does not resolve the problem. Using a mixin could possibly help.
@IanFiddes That's because you derived TransMap_HgmIntronVector from Hgm instead of Base.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.