django.db.utils.ProgrammingError:关系已经存在


73

我正在尝试为新的django项目设置表(也就是说,数据库中不存在这些表);django版本是1.7,数据库后端是PostgreSQL。该项目的名称是crud。迁移尝试的结果如下:

python manage.py makemigrations crud

Migrations for 'crud':
  0001_initial.py:
    - Create model AddressPoint
    - Create model CrudPermission
    - Create model CrudUser
    - Create model LDAPGroup
    - Create model LogEntry
    - Add field ldap_groups to cruduser
    - Alter unique_together for crudpermission (1 constraint(s))

python manage.py migrate crud

Operations to perform:
  Apply all migrations: crud
Running migrations:
  Applying crud.0001_initial...Traceback (most recent call last):
  File "manage.py", line 18, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 377, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute
    output = self.handle(*args, **options)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/commands/migrate.py", line 161, in handle
    executor.migrate(targets, plan, fake=options.get("fake", False))
  File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 68, in migrate
    self.apply_migration(migration, fake=fake)
  File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 102, in apply_migration
    migration.apply(project_state, schema_editor)
  File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/migration.py", line 108, in apply
    operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
  File "/usr/local/lib/python2.7/dist-packages/django/db/migrations/operations/models.py", line 36, in database_forwards
    schema_editor.create_model(model)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/schema.py", line 262, in create_model
    self.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/schema.py", line 103, in execute
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 82, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 66, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 66, in execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "crud_crudpermission" already exists

迁移文件中的一些要点:

dependencies = [
    ('auth', '0001_initial'),
    ('contenttypes', '0001_initial'),
]
    migrations.CreateModel(
        name='CrudPermission',
        fields=[
            ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ('_created_by', models.CharField(default=b'', max_length=64, null=True, editable=False, blank=True)),
            ('_last_updated_by', models.CharField(default=b'', max_length=64, null=True, editable=False, blank=True)),
            ('_created', models.DateTimeField(null=True, editable=False, blank=True)),
            ('_last_updated', models.DateTimeField(null=True, editable=False, blank=True)),
            ('domain', models.CharField(max_length=32, choices=[(b'town', b'Town'), (b'boe', b'BOE'), (b'police', b'Police')])),
            ('ldap_group', models.CharField(max_length=128, verbose_name=b'LDAP group')),
            ('can_add', models.BooleanField(default=False, verbose_name=b'add')),
            ('can_change', models.BooleanField(default=False, verbose_name=b'change')),
            ('restrict_change_to_own', models.BooleanField(default=False)),
            ('can_delete', models.BooleanField(default=False, verbose_name=b'delete')),
            ('restrict_delete_to_own', models.BooleanField(default=False)),
            ('models', models.ManyToManyField(to='contenttypes.ContentType', null=True, blank=True)),
        ],
        options={
            'verbose_name': 'CRUD permission',
        },
        bases=(models.Model,),
    ),
    migrations.AlterUniqueTogether(
        name='crudpermission',
        unique_together=set([('ldap_group', 'can_add', 'can_change', 'can_delete', 'domain')]),
    )

Crud应用程序实际上并不意味着要执行任何操作,但是我将其用于其他应用程序,因此当我尝试从该应用程序迁移时,会触发上述问题。

我在存在类似问题的人们的网络上找到了其他示例,但是似乎没有一个案例适用,因为

  1. 该问题影响到整个关系,而不仅仅是一列
  2. 我没有使用多重继承。

我应该下一步去寻找潜在的问题?


6
你跑了syncdb吗?如果是这样,则已经在数据库中创建了表,因此此迁移正在尝试重新创建。要跳过它,请运行python manage.py migrate --fake
Timmy O'Mahony,2015年

4
syncdb只是一个迁移,如果没有超级用户,则提示创建超级用户。如果他确实运行了该迁移,则迁移将不会尝试重新应用该迁移。
shangxiao

Answers:


72

这个工作很好

./manage.py migrate --fake default

来源:-https : //github.com/nijel/weblate/issues/587


8
我总是忘记什么是“默认”,所以我想提一下,这是django设置中数据库配置文件的名称-docs.djangoproject.com/en/1.9/ref/settings/#databases
TitanFighter

17
使用假选项时请小心。它只是通过使存储在db中的迁移与本地文件夹匹配来使问题静音,但是在进行下一次迁移时,事情将变得非常错误,因此除非您真正了解发生了什么,否则我建议您不要使用“ fake”。
最大

@max-您的意思是什么事情会出错?当我遇到相同的编程错误时,我已经使用了几次伪选项。到目前为止,我还没有遇到任何问题。我无法迁移的ATM,因为在我的应用中进行迁移后,表已经退出。突然--fake无法解决此问题。
Xeberdee '16

2
@Xeberdee的伪造选项将使django假定您已迁移。如果碰巧甚至没有任何小东西被迁移,那么它也不会迁移,因为您使用了伪造的选项。如果我知道唯一的变化就是django抱怨的表,并且我进行健全性检查以确保表实际上以相同的名称存在,那么我只会使用伪选项。我的观点是,如果您有2个更改,其中之一是已经存在的创建表,则如果您进行伪造,则第二个更改将不会生效。
最大

2
Showmigrations会告诉您数据库在迁移方面的位置-并且Migrations文件夹中存在具有相同名称的文件。这些应该匹配吗?您是在说数据库实际上可以处于与认为不同的状态吗?这能使假货成为可能吗?没有太多要阅读的文档。链接
Xeberdee


6

面临类似的问题,最终删除了迁移文件夹中的所有.py文件(django 1.7自动创建了一个),此后运行良好。


4
这有什么副作用吗?
Vardan

4
在生产中迁移时会引起问题。尝试此操作或仅针对初始迁移或在开发中转储数据库
Arjunsingh

6

在现有模型中添加几个新字段时,我遇到了类似的问题。我正在使用Django 1.9,它引入了 --run-syncdboption。运行manage.py migrate --run-syncdb固定我的桌子。


这对我的情况有所帮助,因为有必要为我的自定义定义的AUTH_USER_MODEL创建一个新表,因此此选项--run-syncdb实现了所需的结果
Iulian Pinzaru

5

我遇到了类似的问题,其中我更改了列名。我遇到了与他问题一起提供的堆栈跟踪中提到的错误。

这就是我所做的。

我先进行假迁移。然后我从django_migrations表中删除了它(我想运行的迁移)条目,然后再次运行迁移(这次没有伪造)。

出现了预期的变化。

希望这会有所帮助。


1
这对我来说没有任何意义,但确实有效。我已将null = True添加到列(django == 1.11)。有人可以解释它为什么起作用吗?
thetanuj

这对于更改列名在django == 2.2中对我有用。
KenBuckley

3

现在(我正在使用Django 1.9),您可以执行以下操作:

./manage.py [--database DATABASE] --fake [app_label] [migration_name]

这样,您可以更准确地定位问题,并且只能在特定数据库上伪造有问题的迁移。

因此,查看问题,您可以:

./manage.py-数据库默认值--fake crud crud.0001_initial


您缺少用于manage.py的实际命令。应该是:./manage.py migrate --database default --fake crud crud.0001_initial
slackmart

3

Django提供了一个--fake-initial我认为有效的选项。从Django迁移文档中

--fake-initial

如果具有该迁移中所有CreateModel操作创建的所有模型名称的所有数据库表均已存在,则允许Django跳过应用程序的初始迁移。此选项适用于首次对已预先使用迁移的数据库运行迁移时使用。但是,此选项不检查匹配表名之外的匹配数据库模式,因此只有在确信现有模式与初始迁移中记录的内容相匹配时,才可以安全使用。

供我使用,我刚刚从版本控制中拉出一个项目,并准备添加一些新的模型字段。我添加了字段,运行./manage.py makemigrations,然后尝试运行./manage.py migrate,这引发了错误,因为正如人们期望的那样,现有数据库中已经存在许多字段。

我应该做的是makemigrations从版本控制中拉出项目以创建现有模型状态的快照后立即运行。然后,./manage.py migrate --fake-initial将是下一步。

之后,您可以正常添加和makemigrations> migrate

注意:我不知道a--fake-initial是否会跳过现有字段添加新字段。我选择注释掉到目前为止我已经创建的新字段,运行--fake-initial好像它是我从版本控制中拉出后所做的第一件事,然后在下一次迁移中添加到更新的字段中。

其他相关文档:https : //docs.djangoproject.com/en/dev/topics/migrations/#initial-migrations


3

我已经处理了好几年了。可能有不同的情况:

场景1:与原始帖子一样,您没有表格开始。在这种情况下,我会

  1. 注释掉models.py中的关系
  2. 运行python manage.py
  3. 假设现在成功迁移
  4. 取消注释您
  5. 在第1步中注释掉了运行python manage.py migrate --fake

方案2:多个应用程序:一种可能性是您可能拥有不同的应用程序,并且一个应用程序的数据模型正在使用另一应用程序中的某些表。在这种情况下,如果数据模型设计正确,则您应该只能为一个应用程序创建表(通过在setting.py中仅指定一个表),然后添加另一个应用程序并进行迁移。如果设计不当心,并且存在递归依赖性,则建议更改设计,而不要进行临时修复。

方案3:您有一些表,迁移时出了点问题,然后我决定

  1. 将models.py恢复为原来的状态,仅引入在models.py中似乎已经存在的新关系。
  2. 删除迁移文件夹
  3. 运行python manage.py makemigrations
  4. 对models.py进行新的更改(如果有的话),并像往常一样继续进行makemigrations和migration命令。

2

当我更改名为member指向另一个表的外键字段时,我在Django 1.10项目中找到并解决了此错误的特定示例。我在三种不同的模型中进行了更改,并在所有模型上均遇到此错误。在我的第一次尝试中,我重命名membermember_user并尝试创建一个新字段member作为指向新表的外键,但这没有用。

我发现的是,当我重命名该member列时,它并没有修改表单中的索引名称,<app>_<model>_<hash>而当我尝试创建一个新列时member列时,它尝试创建相同的索引名称,因为名称的哈希部分是相同的。

我通过member_user临时创建新关系并复制数据解决了该问题。这创建了一个具有不同哈希值的新索引。然后member,我删除并重新创建它,使其指向新表,并带有可能冲突的索引名称。完成此操作后,我将执行RunPython步骤以member使用对适用表的引用填充新列。我通过添加RemoveField迁移来清理临时member_user列来结束。

我确实必须将迁移分为两个文件,因为收到了此错误:

psycopg2.OperationalError:无法更改表“ <table_name>”,因为它具有未决的触发事件

创建并复制数据后,member_user我无法member在同一迁移事务中将其删除。这可能是postgres的特定限制,但是可以通过创建另一个事务并在创建并复制member_user到第二个迁移后移动所有内容来轻松解决。


1

我在web2pyframework中发现了此问题models/config.py

更改

settings.base.migrate = True

在配置文件上

settings.base.migrate = False

问题解决了。


0

我最近遇到了同样的问题,并在这里尝试了一些解决方案。manage.py migrate --fake导致"django_content_type" does not exist错误。如果共享迁移,则同样删除旧迁移可能对其他用户造成问题。

manage.py squashmigrations命令(docs)似乎是解决此问题的理想方法。将旧的迁移压缩为单个迁移(这可以防止不按顺序应用它们),并为任何其他用户保留旧的迁移。至少对我来说,它有效。


-1

不要尝试使用 --fake,因为这样做有可能损坏数据库。

相反,您可以备份当前数据库,重新创建它,然后应用备份。

  1. 创建备份: pg_dump -F c -v -h localhost <database_name> -f tmp/<pick_a_file_name>.psql

  2. 重新创建它: rails db:drop db:create

  3. 恢复备份: pg_restore --exit-on-error --verbose --dbname=<database_name> tmp/<pick_a_file_name>.psql

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.