Ответ 1
Выбор того, как представлять наследование, в основном является проблемой проектирования базы данных. Для производительности одностраничное наследование обычно лучше всего. С хорошей точки зрения базы данных лучше всего наследовать наследование таблицы. Присоединенное наследование таблицы позволяет вам иметь внешние ключи для подклассов, внедренных в базу данных, гораздо проще иметь ненулевые ограничения для полей подкласса. Наследование бетонных таблиц является наихудшим из обоих миров.
Настройка наследования отдельных таблиц с декларативным выглядит следующим образом:
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()
.
Самое главное подумать об использовании наследования для datamapping, заключается в том, действительно ли вам нужно наследование или можно сделать с агрегацией. Наследование будет больно, если вам когда-либо понадобится изменить тип здания, или ваши здания могут иметь как коммерческие, так и жилые аспекты. В таких случаях обычно лучше иметь коммерческие и жилые аспекты как связанные объекты.