简体   繁体   English

Django无法迁移PostgreSQL:关系Y的约束X不存在

[英]Django unable to migrate PostgreSQL: constraint X of relation Y does not exist

I'm trying to run a Django 1.11 migration on a PostgreSQL 9.6.5 database, and I'm getting the odd error: 我正在尝试在PostgreSQL 9.6.5数据库上运行Django 1.11迁移,但遇到了奇怪的错误:

  Applying myapp.0011_auto_20171130_1807...Traceback (most recent call last):
  File "manage.py", line 9, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 364, in execute_from_command_line
    utility.execute()
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 356, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/core/management/base.py", line 283, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/core/management/base.py", line 330, in execute
    output = self.handle(*args, **options)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/core/management/commands/migrate.py", line 204, in handle
    fake_initial=fake_initial,
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 115, in migrate
    state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 145, in _migrate_all_forwards
    state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 244, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/migrations/migration.py", line 129, in apply
    operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/migrations/operations/models.py", line 536, in database_forwards
    getattr(new_model._meta, self.option_name, set()),
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 349, in alter_unique_together
    self._delete_composed_index(model, fields, {'unique': True}, self.sql_delete_unique)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 380, in _delete_composed_index
    self.execute(self._delete_constraint_sql(sql, model, constraint_names[0]))
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/backends/base/schema.py", line 120, in execute
    cursor.execute(sql, params)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/myproject/.env/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: constraint "idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq" of relation "myapp_mymodel" does not exist

The migration is changing a unique contract from including one column to two. 迁移正在将唯一合同从包括一列更改为两列。 Pretty simple. 很简单 It needs to destroy the old index, "idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq", before creating the new one. 在创建新索引之前,它需要销毁旧索引“ idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq”。 However, it fails because it doesn't think the old one exists. 但是,它失败了,因为它认为旧的不存在。

So I connected to the database with pgAdminIII and inspected the table, and contrary to the error message, the table does have an index called idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq . 因此,我使用pgAdminIII连接到数据库并检查了该表,并且与错误消息相反,该表确实具有名为idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq的索引。

I thought maybe Django is using slightly different connection parameters, and is connecting to a different database? 我以为Django使用的连接参数可能略有不同,并且正在连接到其他数据库? Let's try inspecting it from inside a Django dbshell. 让我们尝试从Django dbshel​​l内部对其进行检查。 So I started manage.py dbshell and ran: 因此,我开始了manage.py dbshell并运行:

SELECT *
FROM pg_stat_all_indexes     
WHERE indexrelname='idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq';

and it returned one row. 它返回了一行。

Why is Django unable to see this index during a migration, even though the index definitely exists in the database? 为什么Django在迁移期间看不到该索引,即使该索引确实存在于数据库中?

The problem turned out to be that I converted the database to PostgreSQL from MySQL using the tool pgloader, and this tool converts constraints by creating them as indexes in PostgreSQL, whereas the Django PG backend creates them as constraints. 原来的问题是,我使用pgloader工具将数据库从MySQL转换为PostgreSQL,并且该工具通过在PostgreSQL中将它们创建为索引来转换约束,而Django PG后端将它们创建为约束。 So when the migration runs, it only looks for constraints and doesn't find any. 因此,在运行迁移时,它仅查找约束,而找不到约束。

I fixed this by dropping the index and re-creating it as a true constraint with: 我通过删除索引并将其重新创建为真正的约束来解决此问题:

DROP INDEX idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq;
ALTER TABLE public.myapp_mymodel ADD CONSTRAINT idx_32269_myapp_mymodel_title_333195ae82ac2107_uniq UNIQUE(title);

After that, the Django migration ran correctly. 此后,Django迁移正常运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM