web-dev-qa-db-fra.com

Relations sur les clés composites à l'aide de sqlalchemy

J'ai ce modèle simple de Author - Books et je ne peux pas trouver un moyen de faire de firstName et lastName une clé composite et de l'utiliser en relation. Des idées?

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:pass@library')
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'))            
44
mdob

Le problème est que vous avez défini chacune des colonnes dépendantes comme des clés étrangères séparément, alors que ce n'est pas vraiment ce que vous voulez, vous voulez bien sûr une clé étrangère composite. Sqlalchemy répond à cela en disant (de manière peu claire) qu'il ne peut pas deviner quelle clé étrangère utiliser (firstName ou lastName).

La solution, déclarant une clé étrangère composite, est un peu maladroite en déclarative, mais toujours assez évidente:

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]),
                      {})

L'important ici est que les définitions ForeignKey ont disparu des colonnes individuelles et qu'un ForeignKeyConstraint est ajouté à un __table_args__ variable de classe. Avec cela, le relationship défini sur Author.books fonctionne parfaitement.

75