Использование Python 3.5 и SQLAlchemy 1.0.14 (ORM).
У меня есть таблица элементов, объявленных как таковая:
from sqlalchemy.ext.declarative.api import declarative_base
Base = declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
type = Column(String)
# other non relevant attributes
Мои элементы могут быть разных типов, идентификатор типа хранится в type
.
Для некоторых из этих типов объектов мне нужно иметь определенные методы или атрибуты.
Чтобы добиться этого, я попытался использовать однонаправленное наследование с несколькими SpecialisedItem как подкласс Item:
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
type = Column(String, index=True)
# other non relevant attributes
__mapper_args__ = {
'polymorphic_on': type,
}
class SpecialisedItem(Base):
__mapper_args__ = {
'polymorphic_identity': 'specialitem',
}
def specialised_method(self):
return "I am special"
Теперь, когда я загружаю свои элементы, я хотел бы, чтобы все специализированные элементы (имеющие type=='specialitem'
) загружались как таковые, в то время как любое другое значение типа приводило к загрузке родительского класса Item
.
Это не работает, я получаю AssertionError: No such polymorphic_identity 'normal' is defined
при загрузке элементов.
Я бы хотел избежать создания унаследованных классов, которые ничего не делают для покрытия всех возможных значений type
, вместо этого "unmapped" type
возвращается к родительскому классу Item
.
Есть ли способ достичь этого эффекта?
Минимальный тестовый пример для справки:
from sqlalchemy.engine import create_engine
from sqlalchemy.ext.declarative.api import declarative_base
from sqlalchemy.orm.session import sessionmaker
from sqlalchemy.sql.schema import Column
from sqlalchemy.sql.sqltypes import Integer, String
Base = declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
type = Column(String, index=True)
# other non relevant attributes
__mapper_args__ = {
'polymorphic_on': type,
}
class SpecialisedItem(Item):
__mapper_args__ = {
'polymorphic_identity': 'special',
}
specialAttribute = Column(String)
def specialised_method(self):
return "I am special"
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
session.add(Item(type='normal'))
session.add(Item(type='special'))
session.commit()
# loading only specialized items works
for item in session.query(Item).filter_by(type="special"):
print(item.specialised_method())
# loading other items fails
for item in session.query(Item):
print(item.type)
Спасибо,
Гийом