flask-migrate 处理sqlite数据库报错Constraint must have a name 的解决方案

环境:flask+python+sqlite,我想给某个表里某个字段加unique属性

执行 python manage.py db migrate 没报错,执行 python manage.py db upgrade 的时候报错如下

Traceback (most recent call last):
  File "manage.py", line 29, in <module>
    manager.run()
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/flask_script/__init__.py", line 417, in run
    result = self.handle(argv[0], argv[1:])
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/flask_script/__init__.py", line 386, in handle
    res = handle(*args, **config)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/flask_script/commands.py", line 216, in __call__
    return self.run(*args, **kwargs)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/flask_migrate/__init__.py", line 95, in wrapped
    f(*args, **kwargs)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/flask_migrate/__init__.py", line 280, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/command.py", line 276, in upgrade
    script.run_env()
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/script/base.py", line 475, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/util/pyfiles.py", line 90, in load_python_file
    module = load_module_py(module_id, path)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/util/compat.py", line 156, in load_module_py
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "migrations/env.py", line 100, in <module>
    run_migrations_online()
  File "migrations/env.py", line 94, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/runtime/environment.py", line 839, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/runtime/migration.py", line 361, in run_migrations
    step.migration_fn(**kw)
  File "/app/fusionwork_deployment/api/migrations/versions/ce7abee10440_.py", line 22, in upgrade
    batch_op.create_unique_constraint(None, ['ip'])
  File "/app/fusionwork_deployment/venv/lib/python3.6/contextlib.py", line 88, in __exit__
    next(self.gen)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/operations/base.py", line 325, in batch_alter_table
    impl.flush()
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/operations/batch.py", line 100, in flush
    fn(*arg, **kw)
  File "/app/fusionwork_deployment/venv/lib/python3.6/site-packages/alembic/operations/batch.py", line 384, in add_constraint
    raise ValueError("Constraint must have a name")
ValueError: Constraint must have a name

解决方案:

在app/__init__.py文件

增加代码

from sqlalchemy import MetaData

# 定义命名惯例
naming_convention = {
    "ix": 'ix_%(column_0_label)s',
    "uq": "uq_%(table_name)s_%(column_0_name)s",
    "ck": "ck_%(table_name)s_%(column_0_name)s",
    "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
    "pk": "pk_%(table_name)s"
}
# db = SQLAlchemy()
db = SQLAlchemy(metadata=MetaData(naming_convention=naming_convention))

检查 migrations/env.py是否有 render_as_batch=True  配置

context.configure(
connection=connection,
target_metadata=target_metadata,
process_revision_directives=process_revision_directives,
compare_type=True, # 检查字段类型
compare_server_default=True, # 比较默认值
render_as_batch=True, # this is new feature,for sqlite alter table
**current_app.extensions['migrate'].configure_args
)

然后把之前迁移产生的版本文件删掉,重新迁移一次,成功。

 

约束具体用法可参考:https://www.cnblogs.com/cherylgi/p/13841159.html

posted @ 2020-07-22 16:39  醒日是归时  阅读(499)  评论(0编辑  收藏  举报