колба с ошибкой переноса перегонного куба
-
21-12-2019 - |
Вопрос
Я создаю тестовый блог, используя найденное руководство здесь.Это довольно всеобъемлющая информация.Однако у меня возникли проблемы с миграцией перегонного куба.Я могу стереть все версии и создать новую базу данных со всеми столбцами просто отлично.Но когда я добавляю новый столбец, у меня возникают проблемы.Вот код в моем 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()
Все это довольно стандартно.Однако, если бы я добавил случайный столбец в свою таблицу People, например, так:
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' {}
В нем даже не упоминается название столбца, который я создал в stacktrace, так что это наводит меня на мысль, что с другими таблицами что-то не так.В нем упоминается удаление индекса, но я не делаю ничего подобного при миграции, просто добавляю столбец в 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'
Решение
Я последовал за ним ссылка на документ на Flask-Migrate, чтобы посмотреть, как он использует перегонный куб, и там написано:
Команда migrate добавляет новый сценарий миграции.Вы должны просмотреть его и отредактировать, чтобы он был точным, так как перегонный куб не может обнаружить все изменения, которые вы вносите в свои модели.В частности, он не обнаруживает индексы, поэтому их необходимо добавить в скрипт вручную.
Flask-Migrate использует функцию перегонного куба под названием "автогенерация", где она пытается сравнить состояние вашей базы данных с вашими моделями и автоматически создать разницу.
Мы напрямую используем перегонный куб, и я нашел автогенерацию действительно удобной, но мне часто приходится редактировать ее вручную, особенно когда вы имеете дело с индексами и ограничениями.
Поэтому моим решением было бы сделать то, что там написано, и отредактировать файл миграции вручную и удалить строки, которые вам не нужны или являются ложными.