Добавление соглашения об именах в существующую базу данных
Я использую 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 является источником. Перед этой смешанной ситуацией, где каждый из них имеет свою часть, я бы увидел два пути:
-
Тот, который вы исследуете: вы изменяете схему базы данных в соответствии с моделью SQLAlchemy и делаете свой код Python главным. Это наиболее интуитивно понятно, но это не всегда возможно, как по техническим, так и по административным причинам.
-
Признание того, что в СУБД есть информация, которой нет в SQLAlchemy, но, к счастью, она не актуальна для повседневной работы. Ваш лучший шанс - использовать другой инструмент миграции (ETL), который обратный инжиниринг базы данных перед ее миграцией. После завершения миграции вы можете вернуть контроль над новым экземпляром SQLAlchemy (что может потребовать внесения некоторых изменений в новую БД или модель).
Невозможно определить, какой подход будет работать, поскольку у обоих есть свои проблемы. Но я бы подумал о втором методе?
Ответ 2
Мне посчастливилось изменить naming_convention
обратно на {}
в каждой старой миграции, чтобы они работали в правильном историческом контексте.
Все еще совершенно не уверены, какие интересные побочные эффекты это может иметь.
Ответ 3
просто измените th "ck" в соглашении на "ck": "ck_%(table_name)s_%(column_0_name)s"
работает для меня
обратитесь, чтобы ввести описание ссылки здесь