我对 sqlalchemy 下的继承有点困惑,以至于我什至不确定我应该在这里使用哪种类型的继承(单表、连接表、具体)。我有一个基类,其中包含一些在子类之间共享的信息,以及一些完全独立的数据。有时,我需要来自所有类的数据,有时只需要来自子类的数据。这是一个例子:
class Building:
def __init__(self, x, y):
self.x = x
self.y = y
class Commercial(Building):
def __init__(self, x, y, business):
Building.__init__(self, x, y)
self.business = business
class Residential(Building):
def __init__(self, x, y, numResidents):
Building.__init__(self, x, y, layer)
self.numResidents = numResidents
如何使用声明式将其转换为 SQLAlchemy?那么,如何查询 x>5
和 y>3
内的建筑物?或者哪些住宅楼只有一名居民?
最佳答案
选择如何表示继承主要是数据库设计问题。对于性能来说,单表继承通常是最好的。从良好的数据库设计的角度来看,连接表继承更好。连接表继承使您能够拥有由数据库强制执行的子类的外键,为子类字段设置非空约束要简单得多。具体的表继承是两全其美的。
声明式的单表继承设置如下所示:
class Building(Base):
__tablename__ = 'building'
id = Column(Integer, primary_key=True)
building_type = Column(String(32), nullable=False)
x = Column(Float, nullable=False)
y = Column(Float, nullable=False)
__mapper_args__ = {'polymorphic_on': building_type}
class Commercial(Building):
__mapper_args__ = {'polymorphic_identity': 'commercial'}
business = Column(String(50))
class Residential(Building):
__mapper_args__ = {'polymorphic_identity': 'residential'}
num_residents = Column(Integer)
要使其连接表继承,您需要添加
__tablename__ = 'commercial'
id = Column(None, ForeignKey('building.id'), primary_key=True)
到子类。
两种方法的查询基本相同:
# buildings that are within x>5 and y>3
session.query(Building).filter((Building.x > 5) & (Building.y > 3))
# Residential buildings that have only 1 resident
session.query(Residential).filter(Residential.num_residents == 1)
要控制加载哪些字段,您可以使用 query.with_polymorphic()
方法。
考虑使用继承进行数据映射的最重要的事情是您是否真的需要继承或可以使用聚合。如果您需要更改建筑物的类型,或者您的建筑物可以同时具有商业和住宅方面,那么继承将是一件痛苦的事情。在这些情况下,通常最好将商业和住宅方面作为相关对象。
关于python - SQLAlchemy 继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1337095/