2010-03-10 17 views
14

Estoy intentando unirme a la misma tabla en sqlalchemy. Esta es una versión minimalista, de lo que he intentado:Cómo unirse a la misma tabla en sqlalchemy

#!/usr/bin/env python 
import sqlalchemy as sa 
from sqlalchemy import create_engine 
from sqlalchemy.orm import mapper, sessionmaker, aliased 

engine = create_engine('sqlite:///:memory:', echo=True) 

metadata = sa.MetaData() 
device_table = sa.Table("device", metadata, 
    sa.Column("device_id", sa.Integer, primary_key=True), 
    sa.Column("name", sa.String(255), nullable=False), 
    sa.Column("parent_device_id", sa.Integer, sa.ForeignKey('device.device_id')), 
    ) 

class Device(object): 
    device_id = None 
    def __init__(self, name, parent_device_id=None): 
     self.name = name 
     self.parent_device_id = parent_device_id 

    def __repr__(self): 
     return "<Device(%s, '%s', %s)>" % (self.device_id, 
              self.name, 
              self.parent_device_id) 

mapper(Device, device_table) 

metadata.create_all(engine) 

db_session = sessionmaker(bind=engine)() 

parent = Device('parent') 
db_session.add(parent) 
db_session.commit() 

child = Device('child', parent.device_id) 
db_session.add(child) 
db_session.commit() 

ParentDevice = aliased(Device, name='parent_device') 
q = db_session.query(Device, ParentDevice)\ 
    .outerjoin(ParentDevice, 
       Device.parent_device_id==ParentDevice.device_id) 

print list(q) 

Esto me da este error:

ArgumentError: Can't determine join between 'device' and 'parent_device'; tables have more than one foreign key constraint relationship between them. Please specify the 'onclause' of this join explicitly.

Pero yo estoy especificando un onclause para la combinación. ¿Cómo debería estar haciendo esto?

Respuesta

8

Para query.[outer]join, se especifica como una lista de combinaciones (que es diferente a expression.[outer]join.) Así que necesitaba para poner los 2 elementos de la unión, la tabla y el onclause en una tupla, así:

q = db_session.query(Device, ParentDevice)\ 
    .outerjoin(
        (ParentDevice, Device.parent_device_id==ParentDevice.device_id) 
      ) 
3

Su asignador debe especificar la conexión entre los dos elementos, aquí hay un ejemplo: adjacency list relationships.

+0

No pude hacer que esto funcione para el ejemplo anterior, pero gracias por el puntero a ese documento. Me presentó algunas partes de sqlalchemy que no conocía, que me serán útiles en otras partes de mi aplicación. –

+0

Para referencia futura ... [este enlace] (http://www.sqlalchemy.org/docs/orm/relationships.html#adjacency-list-relationships) es más actual y tiene un ejemplo con declarativo. – Russ

Cuestiones relacionadas