2011-09-21 16 views
30

Tengo este modelo simple de Autor-Libros y no puedo encontrar la forma de hacer de FirstName y LastName una clave compuesta y usarla en relación. ¿Algunas ideas?Relaciones en claves compuestas usando sqlalchemy

from sqlalchemy import create_engine, ForeignKey, Column, String, Integer 
from sqlalchemy.orm import relationship, sessionmaker 
from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 
engine = create_engine('mssql://user:[email protected]') 
engine.echo = True 
session = sessionmaker(engine)() 

class Author(Base): 
    __tablename__ = 'authors' 
    firstName = Column(String(20), primary_key=True) 
    lastName = Column(String(20), primary_key=True) 
    books = relationship('Book', backref='author') 

class Book(Base): 
    __tablename__ = 'books' 
    title = Column(String(20), primary_key=True) 
    author_firstName = Column(String(20), ForeignKey('authors.firstName')) 
    author_lastName = Column(String(20), ForeignKey('authors.lastName'))    

Respuesta

52

El problema es que ha definido cada una de las columnas dependientes como claves externas por separado, cuando eso no es realmente lo que se propone, que, por supuesto, quiero una clave externa compuesta. Sqlalchemy está respondiendo a esto diciendo (de una manera no muy clara), que no puede adivinar qué clave externa usar (firstName o lastName).

La solución, se declara una clave externa compuesta, es un poco torpe en declarativa, pero todavía bastante obvia:

class Book(Base): 
    __tablename__ = 'books' 
    title = Column(String(20), primary_key=True) 
    author_firstName = Column(String(20)) 
    author_lastName = Column(String(20)) 
    __table_args__ = (ForeignKeyConstraint([author_firstName, author_lastName], 
              [Author.firstName, Author.lastName]), 
         {}) 

Lo importante aquí es que los ForeignKey definiciones se han ido de las columnas individuales, y una ForeignKeyConstraint se agrega a una variable de clase __table_args__. Con esto, el relationship definido en Author.books funciona a la perfección.

+2

Los [documentos] (http://docs.sqlalchemy.org/en/rel_0_9/core/constraints.html?highlight=check#metadata-foreignkeys) incluyen aclaraciones y ejemplos adicionales: es importante tener en cuenta que 'ForeignKeyConstraint 'es la única forma de definir una clave externa compuesta. Si bien también podríamos haber colocado objetos 'ForeignKey' en ambas columnas, SQLAlchemy no sabría que estos dos valores deberían vincularse juntos: serían dos restricciones de clave externa individuales en lugar de una sola referencia de clave externa compuesta. Dos columnas. – iled

Cuestiones relacionadas