在按基类检索时,方法覆盖失败

时间:2014-09-17 02:00:39

标签: python inheritance orm sqlalchemy multiple-inheritance

我正在使用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功能;这里没有显示。

1 个答案:

答案 0 :(得分:1)

这不是SQLAlchemy的工作方式。就SQLAlchemy而言,在数据库级别ParentChild之间没有技术差异,因此任何一个表中的任何行都可以加载到类中。

您特意要求加载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创建基类。