Question

Je fais un blog de test en utilisant le guide ici.Il est assez complet.Cependant, j'ai de la difficulté avec l'alambic migrations.Je peux effacer toutes les versions, et de tourner une nouvelle base de données avec toutes les colonnes de l'amende juste.Mais, lorsque j'ajoute une nouvelle colonne j'ai des problèmes.Voici le code dans mon 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()

C'est assez standard.Cependant, si je devais ajouter un hasard colonne de mon Peuple tableau, comme ceci:

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

ensuite, exécutez un python manage.py db migrate (qui fonctionne correctement) puis exécutez une python manage.py db upgrade ensuite, j'obtiens l'erreur suivante:

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

Il ne mentionne même pas le nom de la colonne que j'ai créé dans la stacktrace, donc ce qui m'amène à croire que quelque chose est incorrect avec les autres tables.Il mentionne la suppression d'un index, mais je ne fais pas quelque chose de ce genre dans la migration, tout en ajoutant une colonne à l' People table.Est-il quelque chose dans l'alambic que je ne comprends pas?

Comme je l'ai dit, il fonctionne parfaitement trouver quand je tourne une nouvelle base de données et chargement de la configuration.C'est seulement quand je fais un changement et essayer de migrer que alambic me jette ces erreurs.Quelqu'un aurait-il une idée de pourquoi ce qui se passe?

MODIFIER

Juste au cas où les gens ont besoin de voir mon config.py fichier:

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'
Était-ce utile?

La solution

J'ai suivi le lien vers la doc sur le Flacon de Migrer pour voir comment c'est à l'aide de l'alambic, et il dit:

Le migrer commande ajoute un nouveau script de migration.Vous devez examiner et de le modifier pour être précis, comme l'Alambic ne peut pas détecter tous les changements qui vous apportez à vos modèles.En particulier, il ne permet pas de détecter des indices, de sorte ceux qui doivent être ajoutées manuellement le script.

En flacon de Migrer utilise une fonctionnalité de l'alambic appelé "générer automatiquement", où il essaie de comparer l'état de votre base de données avec vos modèles et de créer automatiquement un diff.

Nous utilisons Alambic directement, et j'ai trouvé de générer automatiquement, vraiment pratique, mais je dois le modifier à la main beaucoup, surtout quand vous avez affaire avec des index et des contraintes.

Donc, ma solution serait de faire ce qu'il dit et modifier le fichier de migration par la main et supprimer les lignes que vous ne voulez pas ou sont infondés.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top