So I have a bunch of tables using SQLAlchemy that are modelled as objects which inherit from the result to a call to declarative_base()
. Ie:
Base = declarative_base()
class Table1(Base):
# __tablename__ & such here
class Table2(Base):
# __tablename__ & such here
Etc. I then wanted to have some common functionality available to each of my DB table classes, the easiest way to do this according to the docs is to just do multiple inheritance:
Base = declarative_base()
class CommonRoutines(object):
@classmethod
def somecommonaction(cls):
# body here
class Table1(CommonRoutines, Base):
# __tablename__ & such here
class Table2(CommonRoutines, Base):
# __tablename__ & such here
The thing I don't like about this is A) multiple inheritance in general is a bit icky (gets tricky resolving things like super()
calls, etc), B) if I add a new table I have to remember to inherit from both Base
and CommonRoutines
, and C) really that "CommonRoutines" class "is-a" type of table in a sense. Really what CommonBase
is is an abstract base class which defines a set of fields & routines which are common to all tables. Put another way: "its-a" abstract table.
So, what I'd like is this:
Base = declarative_base()
class AbstractTable(Base):
__metaclass__ = ABCMeta # make into abstract base class
# define common attributes for all tables here, like maybe:
id = Column(Integer, primary_key=True)
@classmethod
def somecommonaction(cls):
# body here
class Table1(AbstractTable):
# __tablename__ & Table1 specific fields here
class Table2(AbstractTable):
# __tablename__ & Table2 specific fields here
But this of course doesn't work, as I then have to A) define a __tablename__
for AbstractTable
, B) the ABC aspect of things causes all sorts of headaches, and C) have to indicate some sort of DB relationship between AbstractTable
and each individual table.
So my question: is it possible to achieve this in a reasonable way? Ideally I'd like to enforce:
CommonBase
/AbstractTable
be abstract (ie cannot be instantiated)It is pretty straigh-forward, you just make declarative_base()
to return a Base
class which inherits from your CommonBase
using cls=
parameter. Also shown in Augmenting The Base docs. Your code might then look similar to below:
class CommonBase(object):
@classmethod
def somecommonaction(cls):
# body here
Base = declarative_base(cls=CommonBase)
class Table1(Base):
# __tablename__ & Table1 specific fields here
class Table2(Base):
# __tablename__ & Table2 specific fields here