SQLAlchemy继承

2024-03-28 12:54:45 发布

您现在位置:Python中文网/ 问答频道 /正文

对于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>5y>3中的建筑?或者哪个住宅楼只有一个住户?


Tags: 数据self信息类型sqlalchemyinitdefbusiness
2条回答

Ants-Aasma的解决方案要优雅得多,但是如果有意将类定义与表定义分开,则需要使用mapper函数将类映射到表。定义类之后,需要定义表:

building = Table('building', metadata,
    Column('id', Integer, primary_key=True),
    Column('x', Integer),
    Column('y', Integer),
)
commercial = Table('commercial', metadata,
    Column('building_id', Integer, ForeignKey('building.id'), primary_key=True),
    Column('business', String(50)),
)
residential = Table('residential', metadata,
    Column('building_id', Integer, ForeignKey('building.id'), primary_key=True),
    Column('numResidents', Integer),
)

然后可以将表映射到类:

mapper(Building, building)
mapper(Commercial, commercial, inherits=Building, polymorphic_identity='commercial')
mapper(Residential, residential, inherits=Building, polymorphic_identity='residential')

然后以蚂蚁Aasma描述的方式与类进行交互。

选择如何表示继承主要是一个数据库设计问题。对于性能来说,单表继承通常是最好的。从一个好的数据库设计角度来看,连接表继承更好。联接表继承使您能够拥有数据库强制执行的子类的外键,对于子类字段具有非空约束要简单得多。具体的表继承是两个世界中最糟糕的。

具有声明性的单表继承设置如下所示:

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()方法。

考虑对数据映射使用继承的最重要的事情是,您是否真的需要继承,或者可以使用聚合。如果你需要改变建筑物的类型,或者你的建筑物可以有商业和住宅两个方面,继承将是一个痛苦。在这些情况下,最好将商业和住宅方面作为相关对象。

相关问题 更多 >