2012-01-15 10 views
5

En SQLAlchemy, imaginemos que tenemos una mesa Foo con una clave primaria compuesta, y Bar, que tiene dos limitaciones clave externa que lo vinculan con Foo (cada Bar tiene dos Foo objetos)SQLAlchemy: Múltiples claves ajenas a una misma mesa con el compuesto principal clave

Mi problema es con la función relationship, lo que me hace repetir la información (en el primaryjoin) que ya he dado en la (SECO viola) ForeightKeyConstraint. ¿Hay alguna otra forma de estructurar esto para que no tenga que repetir información? ¿Alguna forma de pasar el relevante ForeignKeyConstraint al relationship?

class Foo(Base): 
    __tablename__ = "Foo" 
    id_1 = Column(Integer, primary_key=True) 
    id_2 = Column(Integer, primary_key=True) 

class Bar(Base): 
    __tablename__ = "Bar" 
    id = Column(Integer, primary_key=True) 

    foo_1_id_1 = Column(Integer) 
    foo_1_id_2 = Column(Integer) 

    foo_2_id_1 = Column(Integer) 
    foo_2_id_2 = Column(Integer) 

    __table_args__ = (
      ForeignKeyConstraint(
       [foo_1_id_1,foo_1_id_2], 
       [Foo.id_1,Foo.id_2] 
       ), 
      ForeignKeyConstraint(
       [foo_2_id_1,foo_2_id_2], 
       [Foo.id_1,Foo.id_2] 
       ) 
      ) 

    foo_1 = relationship(Foo,primaryjoin="(Bar.foo_1_id_1 == Foo.id_1) & (Bar.foo_1_id_2 == Foo.id_2)") 
    foo_2 = relationship(Foo,primaryjoin="(Bar.foo_2_id_1 == Foo.id_1) & (Bar.foo_2_id_2 == Foo.id_2)") 

Gracias.

Respuesta

2

El relationship(), como está, no puede determinar su configuración completa. Este es siempre el caso cuando hay más de una forma de referirse a la tabla relacionada.
En su ejemplo, parece que sqlalchemy podría ser lo suficientemente inteligente como para adivinar por los nombres de las columnas, pero esto no es lo que hace ni debería ser.

Aunque podría parecer como si tiene información repetición, de hecho se acaba de ser específico sobre su configuración de relación.

Hay, de hecho, la opción para especificar foreign_keys en la configuración relationship(), pero en la actualidad es el propósito sirve tanto diferente, por lo que aún tendrá que configurar primaryjoin.

+0

Gracias. Pero hay repetición. Me doy cuenta de que no sabe qué 'ForeignKeyConstraint' usar. Pero si, por ejemplo, de alguna manera podría dar una referencia al 'ForeignKeyConstraint' relevante a la' relación', y podría descubrir la expresión de unión para sí mismo (como lo hace cuando hay una sola 'ForeignKeyConstraint' en la tabla dada) entonces eso eliminaría la repetición de los detalles de la unión. – DaedalusFall

+0

Es cierto, y de hecho, como se mencionó, existe la posibilidad de proporcionar 'foreign_keys' a la relación, pero actualmente no se usa para inferir la condición' primaryjoin'. Su caso es un buen ejemplo donde podría usarse de esta manera. Pero como se menciona en la respuesta, * actualmente * no es así. Pero, ¿por qué no creas un ticket de solicitud de función en http://www.sqlalchemy.org/trac/ – van

+0

? Voy a querer asegurarme de que no me falta algo obvio, que ha sido el caso más importante hasta el momento con mi SQLAlchemy ¡ay! – DaedalusFall

0

También puede usar foreign_keys y una lista de Llaves externas.

Ver Multiple Join Paths

foo_1 = relationship(Foo, foreign_keys=[foo_1_id_1, foo_2_id_2]) 
foo_2 = relationship(Foo, foreign_keys=[foo_2_id_1, foo_2_id_2]) 
Cuestiones relacionadas