【问题标题】:method override fails when retrieving by base class通过基类检索时方法覆盖失败
【发布时间】:2014-11-10 22:22:36
【问题描述】:

我正在使用 sqlalchemy 模块的 orm 功能来存储对象。这些对象是执行任意任务的自定义“任务”对象。在检索这些对象以供以后执行时,我使用基类进行检索。其他对象在创建并插入数据库时​​继承自此类。每个覆盖都是基类中起作用的部分。我们称其为功函数。不幸的是,检索后,我的对象执行基类工作函数而不是派生类。

看起来像这样:

    class Parent():
      def work(self):
        print 'I am a parent'

    class Child(Parent):
      def work(self):
        print 'I am a child'

sql alchemy session 生成是这样的:

    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 功能;此处未显示。

【问题讨论】:

    标签: python inheritance orm sqlalchemy multiple-inheritance


    【解决方案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 创建一个基类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 2014-03-17
      • 2012-09-15
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      相关资源
      最近更新 更多