1. 程式人生 > 實用技巧 >flask-migrate 處理sqlite資料庫報錯Constraint must have a name 的解決方案

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
)

然後把之前遷移產生的版本檔案刪掉,重新遷移一次,成功。