当我使用SqlAlchemy子类化`declarative_base`时,我得到了什么?

时间:2014-09-21 05:06:45

标签: python sql inheritance sqlalchemy

我有一个简单的SqlAlchemy应用程序:

import sqlalchemy as sa
import sqlalchemy.ext.declarative as dec
import sqlalchemy.engine.url as saurl
import sqlalchemy.orm as saorm
import sqlalchemy.schema as sch
import abc

class ItemTable():
    __tablename__ = 'book_items'

    @abc.abstractmethod
    def _source_key(self):
        pass

    rowid    = sa.Column(sa.Integer, sa.Sequence('book_page_id_seq'), primary_key=True)
    src      = sa.Column(sa.String,  nullable=False, index=True, default=_source_key)
    dlState  = sa.Column(sa.Integer, nullable=False, index=True, default=0)
    url      = sa.Column(sa.String,  nullable=False, unique=True, index=True)
    # [...snip...]

Base = dec.declarative_base(cls=ItemTable)

class TestItem(Base):
    _source_key = 'test'

    def __init__(self, *args, **kwds):
        # Set the default value of `src`. Somehow, despite the fact that `self.src` is being set
        # to a string, it still works.
        self.src = self._source_key

        print(self)
        print(type(self))
        print(super())
        print("IsInstance of ItemTable", isinstance(self, ItemTable))
        print("IsInstance of Table", isinstance(self, sch.Table))
        super().__init__(*args, **kwds)


def test():
    test = TestItem()


if __name__ == "__main__":

    test()

这个想法是表模式在ItemTable中定义,并且某些成员属性被定义为抽象。这可以确保子类定义某些成员属性,然后通过一些__init__() hijink将实例化的子类用作值默认值。

无论如何,这很有用。

我遇到的问题是,我不能为我的生活找出TestItem(Base)的父母到底是怎么回事。我知道它继承自ItemTable(),但dec.declarative_base(cls=ItemTable)的中间继承是将一大堆方法和“东西”插入TestItem(Base),我不知道那里有什么,或者它来自哪里。

我很确定有一些函数会让我的生活变得更容易修改表格中的一行,但因为我不知道TestItem(Base)实际上是什么继承自,我不知道在SqlAlchemy文档中查看所有内容。

文档 declarative_base()

  

新的基类将被赋予一个产生适当的元类   Tablemapper()个对象并根据其进行相应的TestItem(Base)调用   在类和任何子类中以声明方式提供的信息   上课。

这让我觉得可能Tableisinstance(self, sch.Table)的子类,但是isinstance返回false,所以要么不是,要么元类muckery完全破坏{{1 }}

此外,作为TestItem(Base)的子类的Table在逻辑上没有任何意义,因为在查询时会返回TestItem(Base)的实例,每个实例代表一个< EM>行。

无论如何,我完全糊涂了。


更新

@Veedrac在评论中指出ClassName.mro()为您提供了完整的继承。在这种情况下:
TestItem.mro() - &gt;
[<class '__main__.TestItem'>, <class 'sqlalchemy.ext.declarative.api.Base'>, <class '__main__.ItemTable'>, <class 'object'>]

这里有趣的是,SqlAlchemy文档中的sqlalchemy.ext.declarative.api.Base实例为零。

sqlalchemy.ext.declarative.api路径中记录的唯一内容是_declarative_constructor,并且那里有大约2个无用的句子。

1 个答案:

答案 0 :(得分:2)

嗯,这里我的问题的最终解决方案是完全彻底解决转储SqlAlchemy。

我确切知道如何使用SQL实现我想要的功能。我认为SqlAlchemy会让事情变得更容易,但它只会导致继承噩梦和许多奇怪的问题。

我确定 方式可以在SqlAlchemy中管理我想要的内容,但文档非常糟糕,我无法找到它。