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

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

Моя база данных в настоящее время существует и имеет несколько 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, который тоже не назван).

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


person ABM    schedule 02.03.2014    source источник
comment
Вы говорите, что в вашей базе данных уже есть ForeignKeys, но этот подход работает только в том случае, если вы создаете эти ключи через SQLAlchemy. В противном случае вы в настоящее время находитесь в состоянии, когда SQLAlchemy знает, какое имя должно быть, но ничего не находит под этим именем (и, возможно, видит другое имя?). Я не знаю, что здесь обнаруживает SA, но вам в основном нужно воссоздать (или переименовать?) ваши внешние ключи, индексы и т. д.   -  person javex    schedule 05.03.2014
comment
Если вы не опубликовали свою полную схему, существует ошибка с логическими значениями и соглашениями об именах: bitbucket.org/zzzeek/sqlalchemy/issue/3067/   -  person einSelbst    schedule 15.07.2014
comment
Вы смогли это решить? Я столкнулся с аналогичной проблемой.   -  person Basti Vagabond    schedule 02.06.2017


Ответы (4)


просто измените «ck» в соглашении на "ck": "ck_%(table_name)s_%(column_0_name)s"。это работает для меня.

см. см. документацию по sqlalchemy

person 程仕成    schedule 06.05.2019

Я знаю, что этот вопрос старый, но я вижу, что ответ не был принят.

Это сообщение об ошибке говорит вам о том, что вы должны указывать ограничения явно. Ограничения, на которые он ссылается, - это Boolean, Enum и т. Д., Но не внешние ключи или первичные ключи. Итак, просмотрите свою таблицу, где бы у вас ни было логическое значение или Enum, добавьте к нему имя. Например:

is_active = Column(Boolean(name='is_active'))

Это то, что вам нужно сделать.

person ephraimbuddy    schedule 11.03.2020

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

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

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

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

person fralau    schedule 25.04.2018

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

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

person maxm    schedule 13.10.2018