Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relations on composite keys using sqlalchemy

I have this simple model of Author - Books and can't find a way to make firstName and lastName a composite key and use it in relation. Any ideas?

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'))             
like image 671
mdob Avatar asked Sep 21 '11 18:09

mdob


People also ask

How do I create a composite key in SQLAlchemy?

To create a composite primary key, set primary_key to True on each column involved in the key. A boolean argument when set to False adds NOT NULL constraint while creating a column. Its default value is True .

What is relationship in SQLAlchemy?

The relationship function is a part of Relationship API of SQLAlchemy ORM package. It provides a relationship between two mapped classes. This corresponds to a parent-child or associative table relationship.

How do you use a composite primary key?

A composite key is made by the combination of two or more columns in a table that can be used to uniquely identify each row in the table when the columns are combined uniqueness of a row is guaranteed, but when it is taken individually it does not guarantee uniqueness, or it can also be understood as a primary key made ...


1 Answers

The problem is that you have defined each of the dependent columns as foreign keys separately, when that's not really what you intend, you of course want a composite foreign key. Sqlalchemy is responding to this by saying (in a not very clear way), that it cannot guess which foreign key to use (firstName or lastName).

The solution, declaring a composite foreign key, is a tad clunky in declarative, but still fairly obvious:

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

The important thing here is that the ForeignKey definitions are gone from the individual columns, and a ForeignKeyConstraint is added to a __table_args__ class variable. With this, the relationship defined on Author.books works just right.

like image 111
SingleNegationElimination Avatar answered Oct 09 '22 04:10

SingleNegationElimination