实例化多个AbstractConcreteBase问题

时间:2013-02-25 19:57:49

标签: python sqlalchemy

我收到一个错误,我不理解AbstractConcreteBase

my_enum.py中的

class MyEnum(AbstractConcreteBase, Base):
    pass

在enum1.py

class Enum1(MyEnum):
    years = Column(SmallInteger, default=0)

# class MyEnums1:
#    NONE = Enum1()
#    Y1 = Enum1(years=1)

在enum2.py

class Enum2(MyEnum):
    class_name_python = Column(String(50))

在test.py中

from galileo.copernicus.basic_enum.enum1 import Enum1
from galileo.copernicus.basic_enum.enum2 import Enum2
#...

如果我取消注释enum1.py中的三行,我在第二次导入时会出现以下错误。

AttributeError:类型对象'MyEnum'没有属性''

但没有MyEnums1它可以正常工作或MyEnums1在一个单独的文件中工作正常。为什么这个实例会影响导入?无论如何我可以将MyEnums1保存在同一个文件中吗?

1 个答案:

答案 0 :(得分:2)

abstractconcretebase的目的是将非标准操作顺序应用于标准映射过程。通常,映射的工作方式如下:

  1. 定义要映射的类
  2. 定义表
  3. 使用mapper()将类映射到表。
  4. 声明基本上结合了这三个步骤,但这就是它的作用。

    当使用抽象的具体基础时,我们需要完成这个完全特殊的步骤 - 基类需要映射到子类映射到的所有表的 union 。因此,如果你有enum1和enum2,那么“Base”需要映射到“select * from enum1 UNION ALL select * from enum2”。

    这种到UNION的映射不可能是零敲碎打的; MyEnum基类必须同时向mapper()显示每个子表的完整UNION。因此,AbstractConcreteBase执行复杂的任务,重新排列声明性的工作方式,使得基本的MyEnum根本不会映射,直到mapper configuration发生,这在您首次实例化映射的类时会发生。然后,它将自身作为所有现有映射子类的映射基础插入。

    所以基本上通过在类级别实例化一个Enum1()对象,你过早地调用configure_mappers()方式,这样当Enum2()出现时,abstractconcretebase会被烘焙并且进程失败。 / p>

    除此之外,在类级别实例化类似Enum1()的映射类并不完全正确。 ORM映射对象与全局对象完全相反,并且必须始终在特定会话的本地创建。

    编辑:这些类也应该在它们上面有{“具体”:True},这是你收到此消息的部分原因。我试图看看是否可以改进消息。

    编辑2:是的,这里的机制很奇怪。我已经提交了其他可以跳过这个特定错误消息的内容,尽管它现在会以不同的方式失败并且不会更好。让这个更优雅地失败将需要更多的工作。