2012-10-30 64 views
1

我们有几张表格,它们之间有一个声明式继承,我们一直试图使继承“懒惰”,这意味着我们不想急于在父表上加入JOIN。SQLAlchemy惰性声明式继承

例如:

class Entity(Base): 
    __tablename__ = 'entities' 
    id = Column(Integer, primary_key=True) 
    entity_type = Column(String, nullable=False) 
    __mapper_args__ = {'polymorphic_on': entity_type, 'polymorphic_identity': 'entities'} 

class Person(Entity): 
    __tablename__ = 'persons' 
    person_id = Column(None, ForeignKey('entities.id'), primary_key=True) 
    name = Column(String, nullable=False) 
    __mapper_args__ = {'polymorphic_identity': 'persons'} 

当查询的人,总是SQLAlchemy的JOIN的实体上。我希望这是一种懒惰,我找不到任何办法。

但是,当查询实体时,如果该实体是人物,我仍然希望能够接收Person对象。 这就是为什么我们不能简单地让Person与Entity建立关系,或者使用Mixin有一个。

回答

3

这里的Person实体是Entity-> Person的一个连接。如果你只想查询“实体”表开始,然后查询实体对象。如果您想要的只是类型的“人”实体对象,然后在鉴别筛选:

persons = query(Entity).filter_by(entity_type='persons').all() 

以上将返回,而无需使用连接Person对象,并在您访问个人特定的属性的“人”表将被单独选择为每一行。

编辑:好的,你想以相反的方式。首先这是如何可能的,其次是我的建议,改变你的地图。

  1. 您可以随时通过查询对阵表取回从“人”的行:

    ptable = Person.__table__ 
    rows = query(ptable).filter(ptable.c.foo == 'bar').all() 
    

    ,让你回来的元组,而不是Person对象。

  2. 可能的工作,虽然我还没有尝试过了,这将是相当不寻常的,是使用对人非主映射的另一种方式:

    from sqlalchemy.orm import mapper 
    nperson = mapper(Person, Person.__table__, non_primary=True) 
    people = query(nperson).filter(nperson.c.foo == 'bar').all() 
    
  3. 的传承的原因有利于实体表是因为在类继承中,Person被认为是Entity的专业化 - 你得到的每个人实际上只是一个实体,具有一些使其成为Person的额外素质。 ORM认为Person的主键是“entities.id”列。这是因为所有实体子类的空间跨越很多表,但是完整的实体主键仍然完全保留在“entities.id”中的那些值。 ORM还需要在这里看到“entities.entity_type”列以查看对象的类型。如果“人员”加入到“员工”表中并且您有class Employee(Person),则仅查询“人员”表格不仅不会给我们记录的主键(将FK列留在人员的旁边),而且也不会区分人员和员工。

    语义上,这里的使用请求可能表明继承不合适。假设实体有许多子类 - Person,Animal,Vehicle,并且对于每个子类,它都是真正的“记录数据”的子类表,而专用于实体的列实际上只是关联的值,而不是建议将关系建模为人与实体之间一对一。 这个映射会让你准确的加载你想要的行为;针对Person的查询只会针对“persons”,并且访问Person.entity将发出单个SQL语句以获取相应的实体。

  4. 另一个想法是,虽然我看不到你的完整映射,如果“实体”实际上没有任何有意义的数据,除了作为“所有对象的基础”,恕我直言,这是一个就关系数据库而言,它是反模式。在Python中有基类是好的,但我肯定没有对应的数据库表,它只是使查询和更新更加困难。

+0

这很有效,但我们得到了与我们想要的完全相反的结果 - 我们希望能够在不查询实体表的情况下获取Person对象。 – wafwaf

+0

回答编辑。 。 。 。 – zzzeek