web-dev-qa-db-ja.com

sqlalchemy postgresql enumがdb migrateでタイプを作成しない

Flask Python3でWebアプリを開発しています。dbmigrate/upgradeでpostgresql列挙型に問題があります。

モデルに「ステータス」列を追加しました:

class Banner(db.Model):
    ...
    status = db.Column(db.Enum('active', 'inactive', 'archive', name='banner_status'))
    ...

python manage.py db migrateによって生成された移行は次のとおりです:

from alembic import op
import sqlalchemy as sa

def upgrade():
    op.add_column('banner', sa.Column('status', sa.Enum('active', 'inactive', 'archive', name='banner_status'), nullable=True))

def downgrade():
    op.drop_column('banner', 'status')

そして、python manage.py db upgradeを実行すると、エラーが発生します。

...
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) type "banner_status" does not exist
LINE 1: ALTER TABLE banner ADD COLUMN status banner_status

 [SQL: 'ALTER TABLE banner ADD COLUMN status banner_status']

移行によってタイプ「banner_status」が作成されないのはなぜですか?

何が悪いのですか?

$ pip freeze
alembic==0.8.6
Flask==0.10.1
Flask-Fixtures==0.3.3
Flask-Login==0.3.2
Flask-Migrate==1.8.0
Flask-Script==2.0.5
Flask-SQLAlchemy==2.1
itsdangerous==0.24
Jinja2==2.8
Mako==1.0.4
MarkupSafe==0.23
psycopg2==2.6.1
python-editor==1.0
requests==2.10.0
SQLAlchemy==1.0.13
Werkzeug==0.11.9
27
Meatbot

それを使ってこの問題を決めました。

移行のコードを変更しました。移行は次のようになります。

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

def upgrade():
    banner_status = postgresql.ENUM('active', 'inactive', 'archive', name='banner_status')
    banner_status.create(op.get_bind())

    op.add_column('banner', sa.Column('status', sa.Enum('active', 'inactive', 'archive', name='banner_status'), nullable=True))

def downgrade():
    op.drop_column('banner', 'status')

    banner_status = postgresql.ENUM('active', 'inactive', 'archive', name='banner_status')
    banner_status.drop(op.get_bind())

そしていま python manage.py db upgrade\downgradeが正常に実行されました。

50
Meatbot

この方法はもっと簡単だと思います:

_from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

def upgrade():
    # others_column = ...
    banner_status = postgresql.ENUM('active', 'inactive', 'archive', name='banner_status', create_type=False), nullable=False)
_

また、必要に応じて、_postgresql.ENUM_をdowngrade()関数に追加しました。

2
Gofy and Kitty