Alembic воссоздает внешние ключи каждый раз, когда я мигрирую, что приводит к дублированию внешних ключей в моих таблицах.

У меня есть фляжное приложение, использующее sql-alchemy и фляжную миграцию для обработки изменений базы данных. Каждый раз, когда я запускаю миграцию фляги, чтобы создать сценарий для Alembic для обновления базы данных, сценарий содержит команды для создания внешних ключей, которые уже существуют в моей базе данных.

Определение таблицы в моих моделях.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. Я считаю, что это правильно, если вы используете автоматическую схему именования, что, как я полагаю, происходит по умолчанию.

Для настроек, в которых используется автоматическая схема именования, такая как описанная в разделе «Настройка соглашений об именовании ограничений», имя здесь может быть «Нет», так как прослушиватель событий применит имя к объекту ограничения, когда он связан с таблицей.

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

Может ли кто-нибудь определить, что может привести к созданию этих внешних ключей каждый раз, когда я обновляю базу данных?


person Stephen Graham    schedule 04.12.2019    source источник


Ответы (1)


Имена ограничений, которые вы получаете, выглядят так, как будто они взяты из вашей базы данных, а не из SQLAlchemy. Вам нужно добавить шаблоны именования ограничений для всех типов ограничений в метаданные SQLAlchemy, и тогда, я думаю, вы получите согласованные имена. Посмотрите, как это сделать, в Flask-SQLAlchemy документация. Для вашего удобства я копирую пример кода из документов ниже:

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)
person Miguel    schedule 06.12.2019
comment
Спасибо @miguel, я реализовал это и выполнил миграцию базы данных (я использую вашу миграцию фляги (это здорово)). Это создало файл миграции Alembic с инструкциями create_foreign_key, заполненными новым соглашением об именах. op.create_foreign_key(op.f('fk_CabinClasses_AirlineShortCode_Airlines'), 'CabinClasses', 'Airlines', ['AirlineShortCode'], ['AirlineShortCode']) Я сделал обновление, и он добавил внешние ключи, но при последующем выполнении миграции базы данных была создана точно такая же строка create_foreign_key с новым соглашением об именах, как и в прошлый раз. - person Stephen Graham; 10.12.2019