heroku部署flask数据库配置问题?

系统:ubuntu 14.04
在终端运行heroku run python manage.py deploy时出现错误,应该是数据库的问题

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> 12142dd8d120, empty message
Traceback (most recent call last):
  File "manage.py", line 33, in <module>
    manager.run()
  File "/app/.heroku/python/lib/python2.7/site-packages/flask_script/__init__.py", line 412, in run
    result = self.handle(sys.argv[0], sys.argv[1:])
  File "/app/.heroku/python/lib/python2.7/site-packages/flask_script/__init__.py", line 383, in handle
    res = handle(*args, **config)
  File "/app/.heroku/python/lib/python2.7/site-packages/flask_script/commands.py", line 216, in __call__
    return self.run(*args, **kwargs)
  File "manage.py", line 29, in deploy
    upgrade()
  File "/app/.heroku/python/lib/python2.7/site-packages/flask_migrate/__init__.py", line 216, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/command.py", line 174, in upgrade
    script.run_env()
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/script/base.py", line 397, in run_env
    util.load_python_file(self.dir, 'env.py')
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/util/pyfiles.py", line 81, in load_python_file
    module = load_module_py(module_id, path)
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/util/compat.py", line 79, in load_module_py
    mod = imp.load_source(module_id, path, fp)
  File "migrations/env.py", line 87, in <module>
    run_migrations_online()
  File "migrations/env.py", line 80, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/runtime/environment.py", line 797, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/runtime/migration.py", line 312, in run_migrations
    step.migration_fn(**kw)
  File "/app/migrations/versions/12142dd8d120_.py", line 19, in upgrade
    op.add_column('posts', sa.Column('body_html', sa.Text(), nullable=True))
  File "<string>", line 8, in add_column
  File "<string>", line 3, in add_column
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/operations/ops.py", line 1535, in add_column
    return operations.invoke(op)
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/operations/base.py", line 318, in invoke
    return fn(self, operation)
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/operations/toimpl.py", line 123, in add_column
    schema=schema
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/ddl/impl.py", line 172, in add_column
    self._exec(base.AddColumn(table_name, column, schema=schema))
  File "/app/.heroku/python/lib/python2.7/site-packages/alembic/ddl/impl.py", line 118, in _exec
    return conn.execute(construct, *multiparams, **params)
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 914, in execute
    return meth(self, multiparams, params)
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 68, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 968, in _execute_ddl
    compiled
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
    context)
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
    exc_info
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb)
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
    context)
  File "/app/.heroku/python/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 450, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) column "body_html" of relation "posts" already exists
 [SQL: 'ALTER TABLE posts ADD COLUMN body_html TEXT']

我的model文件是这样的:

#-*- coding:utf-8 -*-
from werkzeug.security import generate_password_hash,check_password_hash    #计算密码散列值并进行核对
from flask.ext.login import UserMixin,AnonymousUserMixin   #login扩展的一个类
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
from flask import current_app
from . import db    #从同一级路径下的__init__里导入数据库db
from . import login_manager
from datetime import datetime
from markdown import markdown
import bleach

class Permission:
    FOLLOW=0x01
    COMMENT=0x02
    WRITE_ARTICLES=0x04
    MODERATE_COMMENTS=0x08
    ADMINISTER=0x80

class Role(db.Model):   #用戶角色,管理員或者普通用戶
    __tablename__='roles'
    id=db.Column(db.Integer,primary_key=True)
    name=db.Column(db.String(64),unique=True)
    default=db.Column(db.Boolean,default=False,index=True)
    permissions=db.Column(db.Integer)
    users=db.relationship('User',backref='role',lazy='dynamic')

    @staticmethod
    def insert_roles():
        roles={
            'User':(Permission.COMMENT,True),
            'Administrator':(0xff,False)
            }
        
        for r in roles:
            role=Role.query.filter_by(name=r).first()
            if role is None:
                role=Role(name=r)
            role.permissions=roles[r][0]
            role.default=roles[r][1]
            db.session.add(role)
        db.session.commit()

    def __repr__(self):
        return '<Role %r>' % self.name

class User(UserMixin,db.Model):
    __tablename__='users'
    id=db.Column(db.Integer,primary_key=True)
    email=db.Column(db.String(64),unique=True,index=True)
    username=db.Column(db.String(64),unique=True,index=True)
    password_hash=db.Column(db.String(128))
    role_id=db.Column(db.Integer,db.ForeignKey('roles.id'))
    confirmed=db.Column(db.Boolean,default=False)
    posts=db.relationship('Post',backref='author',lazy='dynamic')
    comments=db.relationship('Comment',backref='author',lazy='dynamic')
    messages=db.relationship('Message',backref='author',lazy='dynamic')
    
    def __repr__(self):
        return '<User %r>' % self.username

    @property   #此装饰器用法请参照胡雪峰官方网站
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter    #此装饰器用法请参照胡雪峰官方网站    
    def password(self,password):
        self.password_hash=generate_password_hash(password)

    def verify_password(self,password):
        return check_password_hash(self.password_hash,password) #返回True或者False

    def generate_confirmation_token(self,expiration=3600):
        s=Serializer(current_app.config['SECRET_KEY'],expiration)
        return s.dumps({'confirm':self.id})

    def confirm(self,token):
        s=Serializer(current_app.config['SECRET_KEY'])
        try:
            data=s.loads(token)
        except:
            return False
        if data.get('confirm') != self.id:
            return False
        self.confirmed=True
        db.session.add(self)
        return True

    def __init__(self,**kwargs):
        super(User,self).__init__(**kwargs)
        if self.role is None:
            if self.email==current_app.config['HULU_ADMIN']:
                self.role=Role.query.filter_by(permissions=0xff).first()
            if self.role is None:
                self.role=Role.query.filter_by(default=True).first() 
    def can(self,permissions):
        return self.role is not None and (self.role.permissions & permissions)==permissions
    def is_administrator(self):
        return self.can(Permission.ADMINISTER)

class AnonymousUser(AnonymousUserMixin):
    def can(self,permissions):
        return False
    def is_administrator(self):
        return False

login_manager.anonymous_user=AnonymousUser

class Post(db.Model):   #博客文章
    __tablename__='posts'
    id=db.Column(db.Integer,primary_key=True)
    title=db.Column(db.Text)
    body=db.Column(db.Text)
    category=db.Column(db.Text)
    timestamp=db.Column(db.DateTime,index=True,default=datetime.utcnow)
    author_id=db.Column(db.Integer,db.ForeignKey('users.id'))
    body_html=db.Column(db.Text)
    comments=db.relationship('Comment',backref='post',lazy='dynamic')

    @staticmethod
    def generate_fake(count=100):
        from random import seed,randint
        import forgery_py
        
        seed()
        for i in range(count):
            u=User.query.filter_by(username="alvy").first()
            p=Post(body=forgery_py.lorem_ipsum.sentences(randint(1,3)),timestamp=forgery_py.date.date(True),author=u)
            db.session.add(p)
            db.session.commit()
    @staticmethod
    def on_changed_body(target,value,oldvalue,initiator):
        allowed_tags=['a','abbr','acronym','b','blockquote','code','em','i','li','ol','pre','strong','ul','h1','h2','h3','p']
        target.body_html=bleach.linkify(bleach.clean(markdown(value,output_format='html'),tags=allowed_tags,strip=True))
db.event.listen(Post.body,'set',Post.on_changed_body)

@login_manager.user_loader  #回调函数,接受用户id,如果能找到用户,则返回用户对象,否则返回None
def load_user(user_id):
    return User.query.get(int(user_id))

class Comment(db.Model):
    __tablename__='comments'
    id=db.Column(db.Integer,primary_key=True)
    body=db.Column(db.Text)
    body_html=db.Column(db.Text)
    timestamp=db.Column(db.DateTime,index=True,default=datetime.utcnow)
    disabled=db.Column(db.Boolean)
    author_id=db.Column(db.Integer,db.ForeignKey('users.id'))
    post_id=db.Column(db.Integer,db.ForeignKey('posts.id'))

    @staticmethod
    def on_changed_body(target,value,oldvalue,initiator):
        allowed_tags=['a','abbr','acronym','b','code','em','i','strong']
        target.body_html=bleach.linkify(bleach.clean(markdown(value,output_format='html'),tags=allowed_tags,strip=True))
db.event.listen(Comment.body,'set',Comment.on_changed_body)

class Message(db.Model):    #首頁留言板模型
    __tablename__='messages'
    id=db.Column(db.Integer,primary_key=True)
    body=db.Column(db.Text)
    timestamp=db.Column(db.DateTime,index=True,default=datetime.utcnow)
    author_id=db.Column(db.Integer,db.ForeignKey('users.id'))    

求大神解答问题所在?


删除迁移仓库重新创建数据库就好了

阅读 4.8k
3 个回答

看traceback,应该是某个键重复了,清空一下服务器的数据库再试试

不用heroku能正常么

是这个样子,你的数据库已经包含了最新的表,你在运行时重复更新,将一个字段添加了两次,导致的失败

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进