使用sqlalchemy复合键的关系

问题描述:

我有这个简单的作者 - 书籍模型,并找不到一种方法,使firstName和lastName复合键,并在关系中使用它。有任何想法吗?使用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'))    

的问题是,您已经定义每个因列作为单独的外键,当这不是真的你想什么,你当然希望有一个复合外键。 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工作正常。

+2

[docs](http://docs.sqlalchemy.org/en/rel_0_9/core/constraints.html?highlight=check#metadata-foreignkeys)包含额外的说明和示例:重要的是要注意'ForeignKeyConstraint '是定义复合外键的唯一方法。虽然我们也可以在两个列上放置单独的ForeignKey对象,但SQLAlchemy不会意识到这两个值应该配对在一起 - 这将是两个单独的外键约束,而不是单个复合外键引用两列。 – iled