使用 sqlalchemy 的复合键关系

Posted

技术标签:

【中文标题】使用 sqlalchemy 的复合键关系【英文标题】:Relations on composite keys using sqlalchemy 【发布时间】:2011-11-22 05:10:48 【问题描述】:

我有这个简单的 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: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'))            

【问题讨论】:

【参考方案1】:

问题是您已将每个依赖列分别定义为外键,当这不是您真正想要的时,您当然想要一个复合外键。 Sqlalchemy 对此的回应是(以一种不太清楚的方式),它无法猜测要使用哪个外键(firstNamelastName)。

声明复合外键的解决方案在声明中有点笨拙,但仍然相当明显:

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__ 类变量中。这样,Author.books 上定义的 relationship 就可以正常工作了。

【讨论】:

docs 包括额外的说明和示例:需要注意的是,ForeignKeyConstraint 是定义复合外键的唯一方法。虽然我们也可以在两个 [...] 列上放置单独的 ForeignKey 对象,但 SQLAlchemy 不会意识到这两个值应该配对在一起 - 这将是两个单独的外键约束而不是单个复合外键引用两列。

以上是关于使用 sqlalchemy 的复合键关系的主要内容,如果未能解决你的问题,请参考以下文章

sqlalchemy中复合外键的多个关系

SQLAlchemy:表有多个外键约束关系

SQLAlchemy - 不要对关系强制外键约束

按主键排序 sqlalchemy 关系

SQLAlchemy(三):外键连表关系

Spring OneToMany 与复合键的关系与另一个具有复合键的关系