简体   繁体   中英

What the heck do I get when I subclass `declarative_base` using SqlAlchemy?

I have a simple SqlAlchemy application:

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()

The idea is that the table schema is defined in ItemTable , and certain member attributes are defined as abstract. This ensures child-classes define certain member attributes, that are then used as value defaults by the instantiated child-class via some __init__() hijinks.

Anyways, this much works.

The issue I'm having is that I cannot for the life of me figure out what the hell the parents of TestItem(Base) are. I know it inherits from ItemTable() , but the intermediate inheritance of dec.declarative_base(cls=ItemTable) is inserting a whole bunch of methods and "stuff" into TestItem(Base) , and I don't know what is there, or where it's coming from.

I'm pretty sure there are some functions that would make my life a LOT easier with regard to modifying a row in the table, but since I don't know what TestItem(Base) is actually inheriting from, I have no idea where to look at all in the SqlAlchemy documentation.

The documentation does say about declarative_base() :

The new base class will be given a metaclass that produces appropriate Table objects and makes the appropriate mapper() calls based on the information provided declaratively in the class and any subclasses of the class.

Which makes me think that possibly TestItem(Base) is a child-class of Table , but isinstance(self, sch.Table) returns false, so either it's not, or the metaclass muckery is completely breaking isinstance .

Also, TestItem(Base) being a child-class of Table wouldn't make any sense logically, because you get instances of TestItem(Base) returned when you query, with each instance representing a row .

Anyways, I'm thoroughly confused.


Update:

@Veedrac in the comments pointed out that ClassName.mro() gives you the full inheritance. In this case:
TestItem.mro() ->
[<class '__main__.TestItem'>, <class 'sqlalchemy.ext.declarative.api.Base'>, <class '__main__.ItemTable'>, <class 'object'>]

The fun thing here is that there are zero instances of sqlalchemy.ext.declarative.api.Base anywhere in the SqlAlchemy documentation.

The only thing documented along the sqlalchemy.ext.declarative.api path at all is _declarative_constructor , and there are ~2 unhelpful sentences there.

Well, the end solution to my issues here was to just flat-out dump SqlAlchemy entirely.

I know exactly how to achieve what I want using SQL. I assumed that SqlAlchemy would make things easier, but it just lead to inheritance nightmares and lots of bizarre issues.

I'm sure there is a way to manage what I want in SqlAlchemy, but the documentation is so terrible that I'm unable to find it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM