Pergunta

Estou fazendo um blog de teste usando o guia encontrado aqui.É bastante abrangente.Porém, estou tendo problemas com as migrações do alambique.Posso apagar todas as versões e criar um novo banco de dados com todas as colunas perfeitamente.Mas, quando adiciono uma nova coluna, tenho problemas.Aqui está o código no meu models.py:

modelos.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()

É tudo bastante padrão.No entanto, se eu adicionasse uma coluna aleatória à minha tabela Pessoas, assim:

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

então execute um python manage.py db migrate (que funciona bem) e execute um python manage.py db upgrade então recebo o seguinte erro:

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

Nem menciona o nome da coluna que criei no stacktrace, o que me leva a acreditar que algo está errado com as outras tabelas.Menciona a eliminação de um índice, mas não estou fazendo nada parecido na migração, apenas adicionando uma coluna ao People mesa.É alguma coisa no alambique que eu não entendo?

Como eu disse, funciona perfeitamente quando eu aciono um novo banco de dados e carrego a configuração.Só quando faço uma alteração e tento migrar é que o alambique me lança esses erros.Alguém tem alguma ideia de por que isso está acontecendo?

EDITAR

Apenas no caso de as pessoas precisarem ver meu config.py arquivo:

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'
Foi útil?

Solução

eu segui o link para o documento no Flask-Migrate para ver como está usando o alambique, e diz:

O comando Migrate adiciona um novo script de migração.Você deve revisá-lo e editá-lo para ser preciso, pois o Alambique não pode detectar todas as alterações que você faz para seus modelos.Em particular, ele não detecta índices, então esses precisam ser adicionados manualmente ao script.

Flask-Migrate usa um recurso de alambique chamado "autogenerate", onde tenta comparar o estado do seu banco de dados com seus modelos e criar automaticamente um diff.

Usamos o Alembic diretamente e achei a geração automática muito conveniente, mas tenho que editá-la muito manualmente, especialmente quando você está lidando com índices e restrições.

Portanto, minha solução seria fazer o que diz e editar o arquivo de migração manualmente e remover as linhas que você não deseja ou que são falsas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top