我有一个 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 表中出现多个外键条目:
我发现创建的每个外键的名称都不同,并且数据库迁移脚本中的 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/