错误原因
from sqlalchemy.dialects.postgresql.named_types import ENUM
import enum
db = SQLAlchemy()
class Action(enum.Enum):
active = 0
inactive = 1
class BaseModel(db.Model):
__abstract__ = True
create_id = db.Column(db.Integer, default=1, comment="创建人")
create_time = db.Column(db.DateTime, default=datetime.now, comment="创建时间")
update_id = db.Column(db.Integer, default=1, comment="更新人")
update_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
active = db.Column(ENUM(Action, create_type=True), server_default='active')
# 当执行数据迁移后,由于数据出问题,删除了所有migrate产生的文件,及删除对应数据库表
# 二再一次执行数据迁移时,flask --app manage db migrate没有报错,
# 但是flask --app manage db upgrade一直报错。
# 提示错误为
# sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateObject) 错误: 类型 "action" 已经存在
# [SQL: CREATE TYPE action AS ENUM ('active', 'inactive')];
# 猜想是删除数据表不完全
解决方法
- 方法1:
使用Navicat打开Postgersql数据库找到对应库,执行如下
# 只要删除自定义的枚举类型即可
drop type if exists action; # 删除枚举类型
> OK
> 时间: 0.004s
>
# Postgersql 有关枚举sql命令
select * from pg_type WHERE typname='action'; # 类型查询
select * from pg_enum; # 查询枚举选项
oid enumtypid enumsortorder enumlabel
23890 23889 1 active
23892 23889 2 inactive
23914 23913 1 active
23916 23913 2 inactive
CREATE TYPE action AS ENUM ('active', 'inactive'); # 创建枚举
- 方法2:
修改迁移文件,在ENUM()中添加create_type=False
from sqlalchemy.dialects.postgresql import ENUM
class BaseModel(db.Model):
__abstract__ = True
# 默认字段 default,nullable, primary_key, unique, autoincrement, name, onupdate
create_id = db.Column(db.Integer, default=1, comment="创建人")
create_time = db.Column(db.DateTime, default=datetime.now, comment="创建时间")
update_id = db.Column(db.Integer, default=1, comment="更新人")
update_time = db.Column(db.DateTime, default=datetime.now, onupdate=datetime.now)
active = db.Column(ENUM(Action, create_type=False), server_default='active')
# 定义模型枚举字段时,添加create_type=False,但是在迁移文件中还是没有create_type=False属性。如下
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('auth_dept',
....
sa.Column('active', postgresql.ENUM('active', 'inactive', name='action'), server_default='active', nullable=True)
...)
# 所以解决大方法是在ENUM()中添加create_type=False即可