2011-07-21 8 views
7

Básicamente, tengo este modelo, donde asigné en una sola tabla una clase "BaseNode" y dos subclases. El punto es que necesito una de las subclases, para tener una relación de uno a muchos con la otra subclase. Por lo tanto, en orden, es una relación con otra fila de diferente clase (subclase), pero en la misma tabla. ¿Cómo crees que podría escribirlo usando la sintaxis declarativa ?.SQLAlchemy Relación uno a muchos en herencia de tabla única - declarativo

Nota: debido a otras relaciones en mi modelo, si es posible, realmente necesito seguir con la herencia de una sola tabla.

class BaseNode(DBBase): 
    __tablename__ = 'base_node' 
    id = Column(Integer, primary_key=True) 
    discriminator = Column('type', String(50)) 
    __mapper_args__ = {'polymorphic_on': discriminator} 

class NodeTypeA(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeA'} 
    typeB_children = relationship('NodeTypeB', backref='parent_node') 


class NodeTypeB(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeB'} 
    parent_id = Column(Integer, ForeignKey('base_node.id')) 

Utilizando este código tirará:

sqlalchemy.exc.ArgumentError: NodeTypeA.typeB_children and back-reference NodeTypeB.parent_node are both of the same direction . Did you mean to set remote_side on the many-to-one side ?

Cualquier idea o sugerencia?

Respuesta

8

Estaba luchando con esto antes. Yo era capaz de conseguir esta relación autorreferencial de trabajo:

class Employee(Base): 
    __tablename__ = 'employee' 
    id = Column(Integer, primary_key=True) 
    name = Column(String(64), nullable=False) 
Employee.manager_id = Column(Integer, ForeignKey(Employee.id)) 
Employee.manager = relationship(Employee, backref='subordinates', 
    remote_side=Employee.id) 

Tenga en cuenta que la manager y manager_id son porque no se puede hacer auto-referencias dentro de una definición de clase "parcheado mono-".

Así que en su ejemplo, yo supongo esto:

class NodeTypeA(BaseNode): 
    __mapper_args__ = {'polymorphic_identity': 'NodeTypeA'} 
    typeB_children = relationship('NodeTypeB', backref='parent_node', 
     remote_side='NodeTypeB.parent_id') 

EDITAR: Básicamente lo que su error le está diciendo es que la relación y su backref son ambos idénticos. Entonces, cualquiera sea la regla que aplica SA para averiguar cuáles son las relaciones a nivel de tabla, no coinciden con la información que usted proporciona.

Me enteré de que simplemente diciendo mycolumn=relationship(OtherTable) en su clase declarativa dará como resultado que mycolumn sea una lista, suponiendo que SA pueda detectar una relación no ambigua. Por lo tanto, si realmente desea que un objeto tenga un enlace a su elemento principal, en lugar de sus elementos secundarios, puede definir parent=relationship(OtherTable, backref='children', remote_side=OtherTable.id) en la tabla secundaria. Eso define ambas direcciones de la relación padre-hijo.

+0

Gracias por su rápida respuesta !. Lo intenté, pero sigo teniendo el mismo error. ¿Cómo debo cambiar la clase NodeTypeB ?. En su código define Employee.manager_id, y Employee.manager fuera de la definición de clase. Pero en su propuesta a mi código, no lo hizo. Lo siento, creo que no lo entiendo bien. Atentamente. –

+0

Los documentos de SQLAlchemy dicen que está bien proporcionar cadenas que se evalúan para que pueda evitar el error de sintaxis de referencia automática. Pero nunca lo intenté. – wberry

+0

En NodeTypeB su clave externa es para asset_base. Supongo que es un error tipográfico o que te olvidaste de cambiar el nombre antes de publicarlo. Creo que si cambias ForeignKey ('asset_base.id') a ForeignKey (NodeTypeA.id), entonces estará cerca de mi ejemplo de trabajo. – wberry

Cuestiones relacionadas