SQLAlchemy的類繼承、抽象類

Python中的類繼承是至關容易的,可是在SQLAlchemy中卻不能直接用Python類繼承完成,還要多加一些設置。html

網上關於這個東西,東說西說的很是多,甚至官網都沒有把最簡單的解決方案po出來,取而代之的是很是複雜的Inheritance Configurationsql

首先說最簡單的方案,來自Stackoverflow,親測完美有效,最符合Python類繼承。app

參考:Sqlalchemy: avoiding multiple inheritance and having abstract base classide

正解

在這裏,咱們稱這個方法爲__abstract__方法:code

Base = declarative_base()

class CommonRoutines(Base):
    __abstract__ = True

    id = Column(Integer, primary_key=True)

    def __init__(self):
        # ...

class Foo(CommonRoutines):
    __tablename__ = 'foo'

    name = Column(...)

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

也就是說,抽象類中只要用__abstract__ = True代替__tablename__便可完成一切工做,其它一切都和Python內置的類繼承一摸同樣了。orm

繼承中的類方法和靜態方法

SQLAlchemy的ORM繼承,在classmethodstaticmethod繼承是和Python OOP面向對象的繼承方案一致的。htm

也就是說:對象

  • 被冠之@staticmethod的靜態方法,會被繼承,可是在子類調用的時候,倒是調用的父類同名方法。
  • 被冠之@classmethod的類方法,會被繼承,子類調用的時候就是調用子類的這個方法。

繼承中的外鍵

奇怪的是,SQLAlchemy定義的ORM,在繼承父級ORM時候,Foreign Key外鍵是不能繼承的,它強制要求在子類中從新定義。
參考官方文檔:Mapping Class Inheritance Hierarchies 建議直接用Ctrl-f搜索"foreign`關鍵字,就能看到官方在繼承時,也都要從新定義一遍外鍵。sqlalchemy

再參考:SQLAlchemy Inheritance繼承

class Parent(Base):
    __abstract__ = True

    id = Column('id', Integer, primary_key=True)
    name = Column('name', String)
    age = Column('age', String)
    fk = Column('fk', Integer, ForeignKey('anotherTable.id'), primary_key=True)

class Son(Parent):
    __tablename__ = 'son'

    fk = Column('fk', Integer, ForeignKey('anotherTable.id'), primary_key=True)

其它繼承方案

若是參考別人的方案、官網的方案,會讓你暈頭轉向。
爲了不重複參考別人的東西,這裏貼上一些不是解決方案的解決方案

declarative_base(cls=XX)方法:

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

這樣的缺點是,很難看清繼承關係。

官方的__mapper_args__方法:

class Person(Base):
    __tablename__ = 'people'
    id = Column(Integer, primary_key=True)
    discriminator = Column('type', String(50))
    __mapper_args__ = {'polymorphic_on': discriminator}

class Engineer(Person):
    __tablename__ = 'engineers'
    __mapper_args__ = {'polymorphic_identity': 'engineer'}
    id = Column(Integer, ForeignKey('people.id'), primary_key=True)
    primary_language = Column(String(50))

能夠看出,這個必須在父子類都中分別定義難懂的__mapper_args__屬性。這還不算完,官網中還說各類映射須要不一樣的複雜設置。有興趣可參考官網:https://docs.sqlalchemy.org/e...

相關文章
相關標籤/搜索