Подтвердить что ты не робот

Отношения по составным ключам с использованием sqlalchemy

У меня есть эта простая модель Author - Books и не могу найти способ сделать firstName и lastName составным ключом и использовать его в отношении. Любые идеи?

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'))            
4b9b3361

Ответ 1

Проблема заключается в том, что вы определили каждый из зависимых столбцов как внешние ключи отдельно, когда это не совсем то, что вы намереваетесь, вы, конечно, хотите составной внешний ключ. Sqlalchemy отвечает на это, говоря (не очень понятным образом), что он не может угадать, какой внешний ключ использовать (firstName или lastName).

Решение, объявляющее составной внешний ключ, является довольно сложным в декларативном, но довольно очевидным:

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

Важно то, что определения ForeignKey исчезают из отдельных столбцов, а ForeignKeyConstraint добавляется к переменной класса __table_args__. При этом relationship, определяемый на Author.books, работает правильно.