编程语言
首页 > 编程语言> > Python-Alembic迁移错误烧瓶

Python-Alembic迁移错误烧瓶

作者:互联网

我正在使用指南here创建一个测试博客.它非常全面.但是,我在进行Alembic迁移时遇到了麻烦.我可以删除所有版本,并使用所有列来建立一个新数据库.但是,当我添加新列时,我遇到了问题.这是我的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迁移(效果很好),然后运行python manage.py db升级,然后出现以下错误:

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' {}

它甚至没有提到我在stacktrace中创建的列的名称,因此使我相信其他表有问题.它提到了删除索引,但是在迁移中我没有做任何类似的事情,只是在People表中添加了一个列.我不了解阿勒比奇吗?

就像我说的那样,当我启动一个全新的数据库并加载配置时,它可以完美地找到.只有当我进行更改并尝试迁移时,Alembic才会引发这些错误.有谁知道为什么会这样吗?

编辑

以防万一人们需要查看我的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'

解决方法:

我在Flask-Migrate上关注了the link to the doc,以了解其如何使用Alembic,并说:

The migrate command adds a new migration script. You should review it
and edit it to be accurate, as Alembic cannot detect all changes that
you make to your models. In particular it does not detect indexes, so
those need to be added manually to the script.

Flask-Migrate使用称为“自动生成”的alembic功能,在该功能中尝试将数据库状态与模型进行比较并自动创建差异.

我们直接使用Alembic,我发现autogenerate确实很方便,但是我必须手动编辑它,特别是当您处理索引和约束时.

因此,我的解决方案是按照说的做,并手动编辑迁移文件,并删除不需要的或虚假的行.

标签:flask-sqlalchemy,database-migration,alembic,python
来源: https://codeday.me/bug/20191122/2056671.html