7

I'm bulding an app with Flask and Angular hosted on heroku. I have a problem with migrating heroku postgresql. I'm using flask-migrate which is a tiny wrapper around alembic. Locally everything is fine. I got an exception when I run heroku run upgrade which runs alembic upgrade command.

INFO  [alembic.migration] Context impl PostgresqlImpl.
INFO  [alembic.migration] Will assume transactional DDL.
INFO  [alembic.migration] Running upgrade None -> 19aeffe4063d, empty message
Traceback (most recent call last):
  File "manage.py", line 13, in <module>
    manager.run()
...

   cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (ProgrammingError) relation "users" already exists
 '\nCREATE TABLE users (\n\tid SERIAL NOT NULL, \n\tusername VARCHAR(32), \n\tpassword_hash VARCHAR(128), \n\tPRIMARY KEY (id)\n)\n\n' {}

Simply, alembic is trying to run from the first migration which creates the db. I tried to set explicitly the proper revision with heroku run python manage.py db upgrade +2 or revision number but the exception is the same.

lukas$ heroku run python manage.py db current
Running `python manage.py db current` attached to terminal... up, run.1401
INFO  [alembic.migration] Context impl PostgresqlImpl.
INFO  [alembic.migration] Will assume transactional DDL.
Current revision for postgres://...: None

My guess was that due to ephemeral filesystem of Heroku revision in not stored, but that shouldn't be a problem if I explicitly set the revision, right? :)

How can I set the current head of revision?

Here is relevant code:

Procfile:

web: gunicorn server:app
init: python manage.py db init
upgrade: python manage.py db upgrade

models.py

db = SQLAlchemy()

ROLE_USER = 0
ROLE_ADMIN = 1


class User(db.Model):
  __tablename__ = "users"
  id = db.Column(db.Integer, primary_key = True)
  username = db.Column(db.String(32), unique = True, index = True)
  email = db.Column(db.String(255), unique = True)
  password_hash = db.Column(db.String(128))
  role = db.Column(db.SmallInteger, default = ROLE_USER)
4

1 回答 1

4

您输入的init命令Procfile会创建一个全新的 Alembic 存储库,您只需在开发机器上执行一次。当您部署到新机器时,您需要做的就是运行upgrade命令来创建数据库并将其更新到最新版本。

Alembic 和 Flask-Migrate 有一个名为的命令stamp可以帮助您解决此问题。您可以告诉 Alembic将stamp您选择的修订版写入数据库,而无需触及数据库本身。

例如,如果 Alembic 必须一一完成所有迁移,则在有大量迁移时从头开始创建数据库可能需要很长时间。相反,您可以创建数据库,db.create_all()然后运行:

$ ./manage.py db stamp HEAD

并以此将数据库标记为已更新。

另外,在某些时候,我赞成将维护命令Procfile放在web. 要升级数据库,我认为显式运行命令更可预测:

$ heroku run python manage.py db upgrade
于 2014-01-04T18:06:23.153 回答