фляга с ошибкой переноса перегонного куба

Я делаю тестовый блог, используя руководство, найденное здесь. Это довольно всеобъемлюще. Однако у меня проблемы с миграцией перегонных кубов. Я могу стереть все версии и запустить новую базу данных со всеми столбцами. Но когда я добавляю новый столбец, у меня возникают проблемы. Вот код в моем models.py:

models.py

....
class Person(db.Model):
    __tablename__ = 'person'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(100), unique=True)
    pwdhash = db.Column(db.String(100))
    name = db.Column(db.String(100), unique=True)

    def __init__(self, email, name, password):
        self.email = email
        self.name = name.title()
        self.set_password(password)

    def __repr__(self):
        return '<User %r>' % (self.name)

    def set_password(self, password):
        self.pwdhash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.pwdhash, password)

    @classmethod
    def all(cls):
        return Person.query.all()

class Category(db.Model):
    __tablename__ = 'category'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), unique=True)
    description = db.Column(db.Text)

    def __unicode__(self):
        return self.name

class Article(db.Model):
    __tablename__ = 'articles'
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100))
    body = db.Column(db.Text)
    created = db.Column(db.DateTime, default=datetime.datetime.now)
    category_name = db.Column(db.String(10), db.ForeignKey(Category.name))
    category = db.relationship(Category)
    person_name = db.Column(db.String(100), db.ForeignKey(Person.name, onupdate="CASCADE", ondelete="CASCADE"))
    person = db.relationship(Person)

    @property
    def slug(self):
        return urlify(self.title)

    @classmethod
    def all(cls):
        return Article.query.order_by(desc(Article.created)).all()

    @classmethod
    def find_by_category(cls, category):
        return Article.query.filter(Article.category_name == category).all()

Все довольно стандартно. Однако, если бы я добавил случайный столбец в свою таблицу «Люди», например:

class Person(db.Model):
    ....
    random_column = db.Column(db.Integer())

затем запустите python manage.py db migrate (который работает нормально), затем запустите python manage.py db upgrade, после чего я получаю следующую ошибку:

Traceback (most recent call last):
  File "manage.py", line 7, in <module>
    manager.run()
  File "/Library/Python/2.7/site-packages/flask_script/__init__.py", line 397, in run
    result = self.handle(sys.argv[0], sys.argv[1:])
  File "/Library/Python/2.7/site-packages/flask_script/__init__.py", line 376, in handle
    return handle(app, *positional_args, **kwargs)
  File "/Library/Python/2.7/site-packages/flask_script/commands.py", line 145, in handle
    return self.run(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/flask_migrate/__init__.py", line 82, in upgrade
    command.upgrade(config, revision, sql = sql, tag = tag)
  File "/Library/Python/2.7/site-packages/alembic/command.py", line 124, in upgrade
    script.run_env()
  File "/Library/Python/2.7/site-packages/alembic/script.py", line 199, in run_env
    util.load_python_file(self.dir, 'env.py')
  File "/Library/Python/2.7/site-packages/alembic/util.py", line 198, in load_python_file
    module = load_module(module_id, path)
  File "/Library/Python/2.7/site-packages/alembic/compat.py", line 55, in load_module
    mod = imp.load_source(module_id, path, fp)
  File "migrations/env.py", line 72, in <module>
    run_migrations_online()
  File "migrations/env.py", line 65, in run_migrations_online
    context.run_migrations()
  File "<string>", line 7, in run_migrations
  File "/Library/Python/2.7/site-packages/alembic/environment.py", line 652, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/Library/Python/2.7/site-packages/alembic/migration.py", line 225, in run_migrations
    change(**kw)
  File "migrations/versions/4171a9f6ed2a_.py", line 19, in upgrade
    op.drop_index('category_name_key', 'category')
  File "<string>", line 7, in drop_index
  File "<string>", line 1, in <lambda>
  File "/Library/Python/2.7/site-packages/alembic/util.py", line 293, in go
    return fn(*arg, **kw)
  File "/Library/Python/2.7/site-packages/alembic/operations.py", line 716, in drop_index
    self._index(name, table_name, ['x'], schema=schema)
  File "/Library/Python/2.7/site-packages/alembic/ddl/impl.py", line 164, in drop_index
    self._exec(schema.DropIndex(index))
  File "/Library/Python/2.7/site-packages/alembic/ddl/impl.py", line 76, in _exec
    conn.execute(construct, *multiparams, **params)
  File "/Library/Python/2.7/site-packages/sqlalchemy/engine/base.py", line 662, in execute
    params)
  File "/Library/Python/2.7/site-packages/sqlalchemy/engine/base.py", line 720, in _execute_ddl
    compiled
  File "/Library/Python/2.7/site-packages/sqlalchemy/engine/base.py", line 874, in _execute_context
    context)
  File "/Library/Python/2.7/site-packages/sqlalchemy/engine/base.py", line 1024, in _handle_dbapi_exception
    exc_info
  File "/Library/Python/2.7/site-packages/sqlalchemy/util/compat.py", line 196, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb)
  File "/Library/Python/2.7/site-packages/sqlalchemy/engine/base.py", line 867, in _execute_context
    context)
  File "/Library/Python/2.7/site-packages/sqlalchemy/engine/default.py", line 324, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.InternalError: (InternalError) cannot drop index category_name_key because constraint category_name_key on table category requires it
HINT:  You can drop constraint category_name_key on table category instead.
 '\nDROP INDEX category_name_key' {}

В нем даже не упоминается имя столбца, который я создал в трассировке стека, что наводит меня на мысль, что с другими таблицами что-то не так. В нем упоминается удаление индекса, но я ничего подобного в миграции не делаю, просто добавляю столбец в таблицу People. Это что-то в перегонном кубе, чего я не понимаю?

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

ИЗМЕНИТЬ

На всякий случай людям нужно увидеть мой файл config.py:

config.py

import os
basedir = os.path.abspath(os.path.dirname(__file__))

#-----Config the app
SECRET_KEY = 'my_key'
CSRF_ENABLED = True

#-----Config Database
SQLALCHEMY_DATABASE_URI = 'postgresql://username:changeme@localhost/test'
SQLALCHEMY_COMMIT_ON_TEARDOWN = True
SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository')

#-----Config Upload folder
UPLOAD_FOLDER = os.path.realpath('./snb/static') + '/uploads'

person Alex Chumbley    schedule 26.02.2014    source источник
comment
Я не уверен, каково реальное решение, но временный обходной путь, который я придумал, заключается в том, чтобы вручную закомментировать оскорбительную строку в вашем файле ревизии, то есть alembic/versions/jkfldsjlk_my_revision.py   -  person Stephen Fuhry    schedule 12.03.2014


Ответы (1)


Я перешел по ссылке на документ на Flask-Migrate, чтобы увидеть, как он использует перегонный куб, и он говорит:

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

Flask-Migrate использует функцию перегонного куба под названием «автогенерация», где он пытается сравнить состояние вашей базы данных с вашими моделями и автоматически создать diff.

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

Поэтому моим решением было бы сделать то, что он говорит, и отредактировать файл миграции вручную и удалить строки, которые вам не нужны или являются ложными.

person Rachel Sanders    schedule 08.05.2014