【问题标题】:alembic autogenerate after primary key rename failing主键重命名失败后alembic自动生成
【发布时间】:2019-11-19 04:05:10
【问题描述】:

为了更好地判断,我决定将数据库中的主列从 id 重命名为 key,因为我不想与 Python 的 id 函数发生冲突。

我使用batch migrations 设法使用 alembic 重命名列,因为我使用的是 SQLite 后端。

现在,当向我的模型添加新表时,alembic 设法检测到新表,然后崩溃并出现以下情况:

sqlalchemy.exc.NoReferencedColumnError: Could not initialize target column for ForeignKey 'tests.id' on table 'runs': table 'tests' has no column named 'id'

我有一个名为 tests 的表和一个名为 runs 的表,它们通过外键链接:

class Base():
    key = Column(Integer, primary_key=True)

BASE = declarative_base(cls=Base)

class Test(BASE):
     runs = relationship("Run", back_populates="test",
                         cascade="all, delete, delete-orphan")

class Run(BASE):
     test_id = Column(Integer, ForeignKey("tests.key"))
     test = relationship("Test", back_populates="runs")

看起来alembic 在尝试自动生成时正在尝试重新创建所有迁移。或者至少是表创建。

我做错了吗?或者这是 alembic 中的错误?

以下是完整的命令输出,其中包含我的路径。

$ alembic -n testing revision --autogenerate -m "Add sessions table"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.autogenerate.compare] Detected added table 'sessions'
Traceback (most recent call last):
  File "bin/alembic", line 10, in <module>
    sys.exit(main())
  File "lib64/python3.6/site-packages/alembic/config.py", line 540, in main
    CommandLine(prog=prog).main(argv=argv)
  File "lib64/python3.6/site-packages/alembic/config.py", line 534, in main
    self.run_cmd(cfg, options)
  File "lib64/python3.6/site-packages/alembic/config.py", line 514, in run_cmd
    **dict((k, getattr(options, k, None)) for k in kwarg)
  File "lib64/python3.6/site-packages/alembic/command.py", line 197, in revision
    script_directory.run_env()
  File "lib64/python3.6/site-packages/alembic/script/base.py", line 475, in run_env
    util.load_python_file(self.dir, "env.py")
  File "lib64/python3.6/site-packages/alembic/util/pyfiles.py", line 90, in load_python_file
    module = load_module_py(module_id, path)
  File "lib64/python3.6/site-packages/alembic/util/compat.py", line 177, 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 "alembic/env.py", line 71, in <module>
    run_migrations_online()
  File "alembic/env.py", line 65, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "lib64/python3.6/site-packages/alembic/runtime/environment.py", line 839, in run_migrations
    self.get_context().run_migrations(**kw)
  File "lib64/python3.6/site-packages/alembic/runtime/migration.py", line 351, in run_migrations
    for step in self._migrations_fn(heads, self):
  File "lib64/python3.6/site-packages/alembic/command.py", line 173, in retrieve_migrations
    revision_context.run_autogenerate(rev, context)
  File "lib64/python3.6/site-packages/alembic/autogenerate/api.py", line 433, in run_autogenerate
    self._run_environment(rev, migration_context, True)
  File "lib64/python3.6/site-packages/alembic/autogenerate/api.py", line 473, in _run_environment
    autogen_context, migration_script
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 25, in _populate_migration_script
    _produce_net_changes(autogen_context, upgrade_ops)
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 51, in _produce_net_changes
    autogen_context, upgrade_ops, schemas
  File "lib64/python3.6/site-packages/alembic/util/langhelpers.py", line 303, in go
    fn(*arg, **kw)
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 83, in _autogen_for_tables
    autogen_context,
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 225, in _compare_tables
    metadata_table,
  File "lib64/python3.6/site-packages/alembic/util/langhelpers.py", line 303, in go
    fn(*arg, **kw)
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 994, in _compare_foreign_keys
    for fk in conn_fks
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 994, in <genexpr>
    for fk in conn_fks
  File "lib64/python3.6/site-packages/alembic/autogenerate/compare.py", line 400, in __init__
    ) = _fk_spec(const)
  File "lib64/python3.6/site-packages/alembic/util/sqla_compat.py", line 77, in _fk_spec
    target_schema = constraint.elements[0].column.table.schema
  File "lib64/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 855, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "lib64/python3.6/site-packages/sqlalchemy/sql/schema.py", line 2039, in column
    colname,
sqlalchemy.exc.NoReferencedColumnError: Could not initialize target column for ForeignKey 'tests.id' on table 'runs': table 'tests' has no column named 'id'

【问题讨论】:

    标签: python-3.x sqlite sqlalchemy alembic


    【解决方案1】:

    问题出在数据库本身。我之前的迁移脚本没有通过删除约束并在新键上重新创建来更新 ForeignKey 约束。

    而且由于默认情况下 SQLite 不尊重外键 升级通过了,但是数据库中仍然有旧的约束。

    通过在升级脚本中调用drop_constraintcreate_foreign_key 并使用here 描述的方法指定未命名的约束,我设法在我的测试数据库上正确运行升级脚本并正确运行自动生成。

    随后,我按照the SQLAlchemy docs 中的说明对外键添加了检查,因此下次如果外键不匹配,这样的更改将导致升级失败。

    【讨论】:

      猜你喜欢
      • 2015-05-11
      • 2019-03-10
      • 1970-01-01
      • 2010-12-21
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2012-06-26
      • 2020-11-05
      相关资源
      最近更新 更多