2014-09-21 150 views
0

我有一个简单的SQLAlchemy应用:当我使用SqlAlchemy子类化`declarative_base`时会得到什么?

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__() hijinks将其用作实例化子类的值缺省值。

无论如何,这很有用。

我遇到的问题是,我不能为我的生活弄清楚什么是地狱父母TestItem(Base)是。我知道它从ItemTable()继承,但dec.declarative_base(cls=ItemTable)的中间继承将大量方法和“东西”插入到TestItem(Base)中,我不知道那里有什么,或者它来自哪里。

我敢肯定有一些功能,从而使我的生活轻松了许多关于在修改表中的行,但因为我不知道什么是TestItem(Base)实际上继承,我没有想法在SqlAlchemy文档中查看所有内容。

文档说的declarative_base()

新的基类将给予产生适当 Table对象,并基于在类中声明了该 信息适当mapper()调用元类和该类的任何子类 。

这让我觉得,可能TestItem(Base)是儿童类的Table,但isinstance(self, sch.Table)返回false,所以无论是不是,或元类muckery被彻底打破isinstance

此外,TestItem(Base)是一个儿童类的Table就没有任何意义逻辑,因为你得到的TestItem(Base)情况下返回在查询,使用表示每个实例。

无论如何,我完全困惑。


更新:

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

这里的有趣的事情是,也有sqlalchemy.ext.declarative.api.Base为零情况下的SQLAlchemy文档的任何地方英寸

沿着sqlalchemy.ext.declarative.api路径记录的唯一东西是_declarative_constructor,并且在那里有2个无益的句子。

+0

'ClassName.mro()'为您提供完整的,有序的继承层次结构。那是你在找什么? – Veedrac 2014-09-21 05:20:46

+0

@Veedrac - 嗯.....这是*的东西*。它告诉我:mro []'。这里唯一有趣的地方是'sqlalchemy.ext.declarative.api.Base'在SqlAlchemy文档中不存在**。 – 2014-09-21 05:23:44

+0

SqlAlchemy **拼命**需要某种autodoc工具。它甚至不需要任何其他的东西,只有方法名和一个继承图,这两者都可以自动完成。 – 2014-09-21 05:34:39

回答

1

那么,我这里的问题的最终解决方案是完全抛弃SqlAlchemy转储。

我完全知道如何实现我想要的SQL。我认为SqlAlchemy会让事情变得更简单,但这只会导致继承噩梦和许多奇怪的问题。

我确定有a的方式来管理我想要的SqlAlchemy,但文件是如此可怕,我无法找到它。

+0

我曾经讨厌sqlalchemy也来自一个活跃的记录风格ORM(Django)。但由于技术债务,我被迫使用它。在某个时候它有点点击,我得到为什么身份地图和会话做他们做。它是一个很好的解决方案IMO。 尽管如此,2个月以来,我和我的团队都不愿意使用它,因为它的文档非常混乱和散乱。 由上帝,文件是一个头脑的人试图弄清楚它的哲学如何工作。 最后,我们设法定制它,并让它工作,但我希望它不是那么糟糕初学者不友好 – kunl 2017-04-26 12:03:31

+0

是的,我是在同一条船上。在这一点上(在使用sqlalchemy多于一年之后),我喜欢它的* most *,并且会在没有多少考虑的情况下将它用在裸露的SQL库上。 OTOH,入职经验是燃烧的废话。 – 2017-04-27 01:42:28

+0

根据我的朋友的建议,我打算或者帮助处理文档,或者为来自Django/rails背景的人写一篇非官方的文档。 我在办公室外没有太多时间,但我会尽我所能。你也想帮忙吗? – kunl 2017-04-27 08:43:53

相关问题