我正在使用sqlalchemy模块的orm功能来存储对象。这些对象是执行任意任务的自定义“任务”对象。检索这些对象以供以后执行时,我使用基类进行检索。其他对象在创建并插入数据库时从该类继承。每一个都覆盖了确实有效的基类部分。我们称之为工作函数。不幸的是,在检索之后,我的对象执行基类工作函数而不是派生类。
看起来像这样:
class Parent():
def work(self):
print 'I am a parent'
class Child(Parent):
def work(self):
print 'I am a child'
sql炼金术会话生成就像这样:
from sqlalchemy import create_engine
engine = create_engine('mysql+mysqldb://root:@localhost:3306/mercury', pool_recycle=3600)
from sqlalchemy.orm import sessionmaker
session = sessionmaker()
session.configure(bind=engine)
我认为到目前为止正确。插入和检索看起来像这样。
sess = session()
object = Child()
sess.add(Child)
result = sess.query(Parent).limit(1).one()
这是它似乎失败的地方。
result.work()
I am a parent
我也使用mixin来附加orm功能;这里没有显示。
答案 0 :(得分:1)
这不是SQLAlchemy的工作方式。就SQLAlchemy而言,在数据库级别Parent
和Child
之间没有技术差异,因此任何一个表中的任何行都可以加载到类中。
您特意要求加载Parent,因此加载了它。
我认为您正在寻找的模式是polymorphic identity。这将在您的表上创建一个列,允许SQLAlchemy区分不同的类并加载适当的类。
但请注意,多态性身份有点怪癖:
class Person(Base):
__tablename__ = 'people'
type_ = Column(types.String)
__mapper_args__ = {
'polymorphic_identity': None,
'polymorphic_on': type_
}
class Parent(Person):
__mapper_args__ = {
'polymorphic_identity': "parent",
'polymorphic_on': type_
}
def work(self):
print 'I am a parent'
class Child(Person):
__mapper_args__ = {
'polymorphic_identity': "child",
'polymorphic_on': type_
}
def work(self):
print 'I am a child'
None
多态可用于查询所有类型,并将返回适当的类,即:
> session.query(Person).filter(Person.type_ == 'child').first()
Child(type_='child')
但事实并非如此。这将不工作:
> session.query(Parent).filter(Parent.type_ == 'child').one()
NoResultFound: No row was found for one()
换句话说,如果您希望能够按照问题中列出的一般方式进行查询,请确保使用'polymorphic_identity': None
创建基类。