Sqlalchemy:避免多重继承并具有抽象基类

时间:2012-03-07 17:46:34

标签: python sqlalchemy multiple-inheritance

所以我有一堆使用SQLAlchemy的表,它们被建模为从结果继承到declarative_base()的调用的对象。即:

Base = declarative_base()
class Table1(Base):
    # __tablename__ & such here

class Table2(Base):
     # __tablename__ & such here

等。然后我想为每个数据库表类提供一些常用功能,the easiest way to do this according to the docs只是做多重继承:

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

我不喜欢这件事是A)多重继承一般有点狡猾(变得棘手解决像super()调用等),B)如果我添加一个新表我必须记得从BaseCommonRoutines继承,而C)实际上“CommonRoutines”类在某种意义上是“a-a”类型的表。实际上CommonBase是一个抽象基类,它定义了一组字段&所有表共有的例程。换句话说:“它是一个”抽象表。

所以,我想要的是:

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

但这当然不起作用,因为我必须A)为__tablename__定义AbstractTable,B)事物的ABC方面会引起各种令人头疼的问题,并且C)有表示AbstractTable与每个表之间的某种DB关系。

所以我的问题是:是否有可能以合理的方式实现这一目标?理想情况下,我想强制执行:

  • 没有多重继承
  • CommonBase / AbstractTable是抽象的(即无法实例化)

3 个答案:

答案 0 :(得分:29)

SQLAlchemy版本0.7.3引入了__abstract__指令,该指令用于不应映射到数据库表的抽象类,即使它们是 sqlalchemy.ext.declarative.api.Base的子类。 。所以现在你创建一个这样的基类:

Base = declarative_base()

class CommonRoutines(Base):
    __abstract__ = True

    id = Column(Integer, primary_key=True)

    def __init__(self):
        # ...

请注意CommonRoutines如何没有__tablename__属性。然后像这样创建子类:

class Foo(CommonRoutines):
    __tablename__ = 'foo'

    name = Column(...)

    def __init__(self, name):
        super().__init__()
        self.name = name
        # ...

这将映射到表格foo,并从id继承CommonRoutines属性。

来源和更多信息:http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/declarative.html#abstract

答案 1 :(得分:15)

这是非常直截了当的,您只需让declarative_base()返回Base类,该类继承自CommonBase使用cls=参数。同样显示在Augmenting The Base文档中。您的代码可能看起来类似于以下内容:

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

答案 2 :(得分:3)

您可以使用Abstract Concrete Base制作抽象基础模型:

from sqlalchemy.ext.declarative import AbstractConcreteBase


class AbstractTable(AbstractConcreteBase, Base):
    id = db.Column(db.Integer, primary_key=True)

    @classmethod
    def somecommonaction(cls):
        # body here