python - Flask-Sqlalchemy:具有 3 个主键同时也是外键的表

标签 python sqlalchemy foreign-keys flask-sqlalchemy composite-primary-key

我正在尝试将表从纯 SQL 转换为 Flask-Sqlalchemy,但可用的文档不清楚如何执行此特定场景 - 主键也是外键。

建表的SQL如下,运行良好:

CREATE TABLE IF NOT EXISTS `ws`.`Perfil_Plano_Transacao` (
    `pptr_perf_id` INT NOT NULL,
    `pptr_tran_id` INT NOT NULL,
    `pptr_plan_id` INT NOT NULL,
    `pptr_dt_incluscao` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `pptr_dt_atualizacao` TIMESTAMP NULL,
PRIMARY KEY (`pptr_perf_id`, `pptr_tran_id`, `pptr_plan_id`),
INDEX `fk_Perfil_Plano_Transacao_Transacao1_idx` (`pptr_tran_id` ASC),
INDEX `fk_Perfil_Plano_Transacao_Plano1_idx` (`pptr_plan_id` ASC),
CONSTRAINT `fk_Perfil_Plano_Transacao_Perfil1`
    FOREIGN KEY (`pptr_perf_id`)
    REFERENCES `ws`.`Perfil` (`perf_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
CONSTRAINT `fk_Perfil_Plano_Transacao_Transacao1`
    FOREIGN KEY (`pptr_tran_id`)
    REFERENCES `ws`.`Transacao` (`tran_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
CONSTRAINT `fk_Perfil_Plano_Transacao_Plano1`
    FOREIGN KEY (`pptr_plan_id`)
    REFERENCES `ws`.`Plano` (`plan_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

我到这里为止的 Python 代码是:

class PerfilPlanoTransacaoModel(db.Model):

    __tablename__ = 'perfil_plano_transacao'

    pptr_perf_id = db.Column(db.Integer, primary_key=True, autoincrement=False)
    pptr_plan_id = db.Column(db.Integer, primary_key=True, autoincrement=False)
    pptr_tran_id = db.Column(db.Integer, primary_key=True, autoincrement=False)
    pptr_dt_inclusao = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    pptr_dt_atualizacao = db.Column(db.DateTime, nullable=True)

    __table_args__ = (
        db.ForeignKeyConstraint(
            ['pptr_perf_id', 'pptr_plan_id', 'pptr_tran_id'],
            ['perfil.perf_id', 'plano.plan_id', 'transacao.tran_id'],
            ['fk_Perfil_Plano_Transacao_Perfil1', 'fk_Perfil_Plano_Transacao_Plano1', 'fk_Perfil_Plano_Transacao_Transacao1']
        ),
    )

我想知道我是否正朝着正确的方向前进。例如,我没有找到如何声明外键约束的 name 以及如何设置 INDEX。是否有更多的 Flaks-Sqlalchemy 方法来完成这一切?

最佳答案

@Halvor 的回答是正确的,但我要补充一点,你有一个复合主键但没有复合外键,你有三个单列外键指向不同的表,这意味着你可以声明外键在您的列定义中:

from sqlalchemy import ForeignKey

class PerfilPlanoTransacaoModel(db.Model):

    __tablename__ = 'perfil_plano_transacao'

    pptr_perf_id = db.Column(
        db.Integer, 
        ForeignKey('perfil.perf_id'),
        primary_key=True, 
        autoincrement=False,
    )
    pptr_plan_id = db.Column(
        db.Integer, 
        ForeignKey('plano.plan_id'),
        primary_key=True, 
        autoincrement=False,
    )
    pptr_tran_id = db.Column(
        db.Integer, 
        ForeignKey('transacao.tran_id'),
        primary_key=True, 
        autoincrement=False,
    )
    pptr_dt_inclusao = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    pptr_dt_atualizacao = db.Column(db.DateTime, nullable=True)

使用 ForeignKeyConstraint 比使用 ForeignKey 稍微冗长一点,我们在此示例中的列定义中创建的 ForeignKey 对象最终是转换为 ForeignKeyConstraint 对象,在处理单列键时使用 ForeignKey 对象更容易。 __table_args__ 中定义的 ForeignKeyConstraint 对象通常仅在您需要创建复合外键时直接使用,例如,如果您有另一个表想要引用 perfil_plano_transacao ,它需要是一个复合外键,您必须像上面那样定义它。

对于你剩下的问题,我将遵从@Halvor 的回答。

关于python - Flask-Sqlalchemy:具有 3 个主键同时也是外键的表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57576929/

相关文章:

python - 删除 Flask-SQLAlchemy 表引发 AttributeError

python - 在混合字典/列表中查找父 sibling

Python:从 FTP 服务器检索多个文件

sqlalchemy 过滤器和 sql 注入(inject)

php - 调用未定义的方法 Gallery::newQuery() Laravel

php - 如何将新行的 id 插入到另一个链接表中?

mysql - 是否有任何工具可以帮助将 innoDB 表转换为 mysql 集群的 NDB 表?

python - 亚马逊 AWS - python 初学者

python - % 数组中的元组? python(不将元组追加到数组中)

python - SQLAlchemy 的 Unicode 问题