python - 每次迁移时 Alembic 都会重新创建外键,导致表上出现重复的外键

标签 python sqlalchemy flask-sqlalchemy alembic flask-migrate

我有一个 Flask 应用程序,使用 sql-alchemy 和 Flask migrate 来处理数据库更改。每次我运行 Flask migrate 为 Alembic 创建脚本来更新数据库时,该脚本都包含用于创建数据库中已存在的外键的命令。

我的 models.py 中的表定义是

class Airline(db.Model):

    __tablename__ = 'Airlines'
    AirlineID =         db.Column(db.Integer,       primary_key=True)
    AirlineShortCode =  db.Column(db.String(3),     index=True, unique=True, nullable=False)
    FullName =          db.Column(db.String(256),   unique=False, nullable=True)
    ShortName =         db.Column(db.String(64),    unique=False, nullable=True)

class CabinClass(db.Model):

    __tablename__ = 'CabinClasses'
    CabinClassID =         db.Column(db.Integer,     primary_key=True)
    AirlineShortCode =     db.Column(db.ForeignKey("Airlines.AirlineShortCode"), nullable=True)
    CabinClassShortCode =  db.Column(db.String(32),  unique=False, nullable=False)
    CabinClassName =       db.Column(db.String(64),  unique=False, nullable=True)

为创建外键而生成的迁移数据库更新脚本中的行是

    op.create_foreign_key(None, 'CabinClasses', 'Airlines', ['AirlineShortCode'], ['AirlineShortCode'])

每次创建迁移脚本时都会生成此行,从而导致 CabinClasses 表中出现多个外键条目:

enter image description here

我发现创建的每个外键的名称都不同,并且数据库迁移脚本中的 create_foreign_key 命令将名称指定为 None。如果您使用自动命名方案,我相信这是正确的,我相信这是默认情况下发生的情况

For setups that use an automated naming scheme such as that described at Configuring Constraint Naming Conventions, name here can be None, as the event listener will apply the name to the constraint object when it is associated with the table

https://alembic.sqlalchemy.org/en/latest/naming.html

谁能确定什么会导致我每次更新数据库时创建这些外键?

最佳答案

您获得的约束名称看起来像是来自您的数据库,而不是 SQLAlchemy。您需要将所有类型的约束的约束命名模板添加到 SQLAlchemy 元数据中,然后我认为您将获得一致的名称。了解如何在 Flask-SQLAlchemy documentation 中执行此操作。为了您的方便,我从下面的文档中复制了代码示例:

from sqlalchemy import MetaData
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

convention = {
    "ix": 'ix_%(column_0_label)s',
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(constraint_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s"
}

metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(app, metadata=metadata)

关于python - 每次迁移时 Alembic 都会重新创建外键,导致表上出现重复的外键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59181990/

相关文章:

python - SQLAlchemy ORM 中 "aliased"的使用

python - SQLAlchemy-mptt 获取完整树

python - Postgres/SQL炼金术 : no matching unique constraint

python - 获取 Python 对象包

python - 排列 5(或 6)个列表

python - 使用 .contains() 的 SQLAlchemy 搜索太敏感

python - 将记录输入 Postgres 时出现验证错误

SQLAlchemy SELECT id FROM Table_1 WHERE name ='xyz'

python - Python 中的 MVC 模型结构

python - 如何在Python爬虫中访问多页面表单的发布数据