Добавление соглашения об именах в существующую базу данных

Я использую sqlalchemy и пытаюсь интегрировать alembic для миграции базы данных.

Моя база данных в настоящее время существует и имеет ряд ForeignKeys, определенных без имен. Я хотел бы добавить соглашение об именах, чтобы разрешить миграции, которые влияют на столбцы ForeignKey.

Я добавил соглашение об именах, приведенное здесь, в начало моего файла models.py: Ограничения именования 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"
              }

DeclarativeBase = declarative_base()


DeclarativeBase.metadata = MetaData(naming_convention=convention)

def db_connect():
   return create_engine(URL(**settings.DATABASE))

def create_reviews_table(engine):
    DeclarativeBase.metadata.create_all(engine)

class Review(DeclarativeBase):

    __tablename__ = 'reviews'

    id = Column(Integer, primary_key=True)
    review_id = Column('review_id', String, primary_key=True)
    resto_id = Column('resto_id', Integer, ForeignKey('restaurants.id'),
            nullable=True)
    url = Column('url', String),
    resto_name = Column('resto_name', String)

Я установил alembic/env.py в соответствии с инструкциями по обучению, загружая метаданные моей модели в target_metadata.

Когда я запустил

$: alembic current

Я получаю следующую ошибку: sqlalchemy.exc.InvalidRequestError: Соглашение о присвоении имен, включая% (constraint_name) s, требует, чтобы ограничение было явно указано.

В документах говорится: "Эта же функция [генерация имен для столбцов с использованием соглашения об именах] вступает в силу, даже если мы просто используем флаг Column.unique:" 1, поэтому я думаю, что не должно быть проблемы (они продолжают приводить пример с использованием ForeignKey, который также не назван).

Нужно ли мне возвращаться и давать все мои ограничения явным именам, или есть способ сделать это автоматически?

Ответ 1

Это не имеет целью быть окончательным ответом, а также не может ответить на ваш непосредственный технический вопрос, но может ли это быть "философской проблемой"? Либо ваш код SQLAlchemy является источником истины в отношении базы данных, либо RDMS является источником. Перед этой смешанной ситуацией, где каждый из них имеет свою часть, я бы увидел два пути:

  1. Тот, который вы исследуете: вы изменяете схему базы данных в соответствии с моделью SQLAlchemy и делаете свой код Python главным. Это наиболее интуитивно понятно, но это не всегда возможно, как по техническим, так и по административным причинам.

  2. Признание того, что в СУБД есть информация, которой нет в SQLAlchemy, но, к счастью, она не актуальна для повседневной работы. Ваш лучший шанс - использовать другой инструмент миграции (ETL), который обратный инжиниринг базы данных перед ее миграцией. После завершения миграции вы можете вернуть контроль над новым экземпляром SQLAlchemy (что может потребовать внесения некоторых изменений в новую БД или модель).

Невозможно определить, какой подход будет работать, поскольку у обоих есть свои проблемы. Но я бы подумал о втором методе?

Ответ 2

Мне посчастливилось изменить naming_convention обратно на {} в каждой старой миграции, чтобы они работали в правильном историческом контексте.

Все еще совершенно не уверены, какие интересные побочные эффекты это может иметь.