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
)
然后把之前迁移产生的版本文件删掉,重新迁移一次,成功。