如何构建具有复合主键的表的ForeignKey?

时间:2013-03-07 00:22:31

标签: python sqlalchemy flask-sqlalchemy

我在确定如何为我定义的表格正确构建我的ForeignKey列时遇到了很多麻烦。我在这里概述了我的模型(并在我的PhoneNumber模型中的有问题的行旁边发表评论):

class AreaCode(db.Model):
    __tablename__ = 'areacodes'
    area_code = db.Column(db.Integer, primary_key=True)
    exchanges = db.relationship('Exchanges', backref='area_code')


class Exchange(db.Model):
    __tablename__ = 'exchanges'
    exchange = db.Column(db.Integer, primary_key=True)
    area_code_pk = db.Column(db.Integer, db.ForeignKey('areacodes.area_code'), primary_key=True)


class PhoneNumber(db.Model):
    __tablename__ = 'phonenumbers'
    phone_number = db.Column(db.Numeric(precision=4, scale=0), primary_key=True)
    exchange_pk = db.Column(db.Integer, db.ForeignKey('exchanges.exchange'), primary_key=True) # this doesnt work since Exchange has two primary keys

这里发生了什么:

我的Exchange表有一个复合主键。这是我的用例所必需的。

我尝试定义的PhoneNumber表需要一个ForeignKey到Exchange表,但由于Exchange表有一个复合主键,我无法弄清楚如何使关系工作。

任何指导都将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:1)

所以,在与sqlalchemy邮件列表上的几个好人交谈后,我终于找到了上述问题。下面是我的代码的最终版本,它允许我在表之间正确关联:

class AreaCode(db.Model):
    __tablename__ = 'areacodes'

    area_code = db.Column(db.Integer, primary_key=True)


class Exchange(db.Model):
    __tablename__ = 'exchanges'

    exchange = db.Column(db.Integer, primary_key=True)
    area_code_pk = db.Column(db.Integer, db.ForeignKey('areacodes.area_code'),
                             primary_key=True)
    area_code = db.relationship('AreaCode', backref=db.backref('exchanges', lazy='dynamic'))


class PhoneNumber(db.Model):
    __tablename__ = 'phonenumbers'
    __table_args__ = (
        db.ForeignKeyConstraint(
            ['exchange_exchange', 'exchange_area_code_pk'],
            ['exchanges.exchange', 'exchanges.area_code_pk'],
        ),
    )

    phone_number = db.Column(db.Integer, primary_key=True)
    exchange_exchange = db.Column(db.Integer, primary_key=True)
    exchange_area_code_pk = db.Column(db.Integer, primary_key=True)
    exchange = db.relationship('Exchange', backref=db.backref('phone_numbers', lazy='dynamic'))