Python中的類繼承是至關容易的,可是在SQLAlchemy中卻不能直接用Python類繼承完成,還要多加一些設置。html
網上關於這個東西,東說西說的很是多,甚至官網都沒有把最簡單的解決方案po出來,取而代之的是很是複雜的Inheritance Configuration
。sql
首先說最簡單的方案,來自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繼承,在classmethod
和staticmethod
繼承是和Python OOP面向對象的繼承方案一致的。htm
也就是說:對象
@staticmethod
的靜態方法,會被繼承,可是在子類調用的時候,倒是調用的父類同名方法。@classmethod
的類方法,會被繼承,子類調用的時候就是調用子類的這個方法。奇怪的是,SQLAlchemy定義的ORM,在繼承父級ORM時候,Foreign Key
外鍵是不能繼承的,它強制要求在子類中從新定義。
參考官方文檔:Mapping Class Inheritance Hierarchies 建議直接用Ctrl-f
搜索"foreign`關鍵字,就能看到官方在繼承時,也都要從新定義一遍外鍵。sqlalchemy
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...