Python django.db.utils.ProgrammingError: 关系已经存在
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29830928/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
django.db.utils.ProgrammingError: relation already exists
提问by quindraco
I'm trying to set up the tables for a new django project (that is, the tables do NOT already exist in the database); the django version is 1.7 and the db back end is PostgreSQL. The name of the project is crud. Results of migration attempt follow:
我正在尝试为新的 django 项目设置表(即,数据库中尚不存在这些表);django 版本是 1.7,数据库后端是 PostgreSQL。该项目的名称是 crud。迁移尝试的结果如下:
python manage.py makemigrations 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
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
Some highlights from the migration file:
迁移文件中的一些亮点:
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')]),
)
,
,
The crud app is not meant to actually do anything, but I use it another app, so when I try migrate from that app, I trigger the above problem.
crud 应用程序实际上并不打算做任何事情,但我将它用作另一个应用程序,因此当我尝试从该应用程序迁移时,我触发了上述问题。
I've found other examples on the web of people with similar issues, but none of their cases seem to apply because
我在网上找到了其他有类似问题的人的例子,但他们的案例似乎都不适用,因为
- The problem affects an entire relation, not just one column
- I am not using multiple inheritance.
- 该问题影响整个关系,而不仅仅是一列
- 我没有使用多重继承。
Where should I look next to find the underlying problem?
接下来我应该在哪里寻找潜在的问题?
回答by Rickka
Been facing a similar issue, eventually deleted all .py files in migration folder (django 1.7 creates one automatically), worked perfectly after that.
遇到了类似的问题,最终删除了迁移文件夹中的所有 .py 文件(django 1.7 自动创建了一个),之后完美运行。
回答by trex
This works pretty fine
这很好用
./manage.py migrate --fake default
回答by Mudassar Hashmi
Do python manage.py migrate --fake
initally.
一开始就做python manage.py migrate --fake
。
Read https://docs.djangoproject.com/en/1.9/ref/django-admin/#django-admin-migrate
阅读https://docs.djangoproject.com/en/1.9/ref/django-admin/#django-admin-migrate
回答by roboslone
I've faced similar issue when added couple new fields to existing model. I'm using Django 1.9, which introduced--run-syncdb
option. Running manage.py migrate --run-syncdb
fixed my tables.
在向现有模型添加几个新字段时,我遇到了类似的问题。我正在使用 Django 1.9,它引入了--run-syncdb
选项。跑步manage.py migrate --run-syncdb
修好了我的桌子。
回答by Shaun Kruger
I found and solved a particular example of this error in a Django 1.10 project while I was changing a foreign key field named member
to point to a different table. I was changing this in three different models and I hit this error on all of them. In my first attempt I renamed member
to member_user
and tried to create a new field member
as a foreign key pointing at the new table, but this didn't work.
我在 Django 1.10 项目中发现并解决了此错误的一个特定示例,当时我正在更改名为member
指向不同表的外键字段。我在三个不同的模型中改变了这个,我在所有模型上都遇到了这个错误。在我的第一次尝试中,我重命名member
为member_user
并尝试创建一个新字段member
作为指向新表的外键,但这不起作用。
What I found is that when I renamed the member
column it did not modify the index name in the form <app>_<model>_<hash>
and when I tried to create a new member
column it tried to create the same index name because the hash portion of the name was the same.
我发现当我重命名member
列时,它没有修改表单中的索引名称<app>_<model>_<hash>
,当我尝试创建一个新member
列时,它尝试创建相同的索引名称,因为名称的哈希部分是相同的。
I resolved the problem by creating a new member_user
relation temporarily and copying the data. This created a new index with a different hash. I then deleted member
and recreated it pointing at the new table and with it the would-be conflicting index name. Once that was done I ran the RunPython
step to populate the new member
column with references to the applicable table. I finished by adding RemoveField
migrations to clean up the temporary member_user
columns.
我通过member_user
临时创建一个新关系并复制数据解决了这个问题。这创建了一个具有不同哈希值的新索引。然后我删除member
并重新创建它指向新表,并使用它可能会冲突的索引名称。完成后,我运行了使用对适用表的引用RunPython
填充新member
列的步骤。我通过添加RemoveField
迁移来清理临时member_user
列来完成。
I did have to split my migrations into two files because I received this error:
我确实不得不将我的迁移分成两个文件,因为我收到了这个错误:
psycopg2.OperationalError: cannot ALTER TABLE "<table_name>" because it has pending trigger events
psycopg2.OperationalError: 无法 ALTER TABLE "<table_name>" 因为它有挂起的触发事件
After the creation and copy of data into member_user
I was not able to remove member
in the same migration transaction. This may be a postgres specific limitation, but it was easily resolved by creating another transaction and moving everything after creating and copying member_user
into the second migration.
在创建和复制数据后,member_user
我无法member
在同一个迁移事务中删除。这可能是 postgres 特定的限制,但可以通过创建另一个事务并在创建并复制member_user
到第二次迁移后移动所有内容来轻松解决。
回答by Raydel Miranda
Now (I'm using Django 1.9) you can make:
现在(我使用的是 Django 1.9)你可以:
./manage.py [--database DATABASE] --fake [app_label] [migration_name]
./manage.py [--database DATABASE] --fake [app_label] [migration_name]
This way you're targeting the problem with more accuracy, and you can fake only the problematic migration on the specific database.
通过这种方式,您可以更准确地定位问题,并且可以仅伪造特定数据库上有问题的迁移。
So, looking at the question, you could:
所以,看看这个问题,你可以:
./manage.py --database default --fake crud crud.0001_initial
./manage.py --database 默认 --fake crud crud.0001_initial
回答by Vishal Mopari
I was facing the similar issues, where i had changed column name. I was getting same error as mentioned in the stack-trace provided with he question.
我遇到了类似的问题,我更改了列名。我遇到了与他问题提供的堆栈跟踪中提到的相同的错误。
Here's what I did.
这就是我所做的。
I ran fake migrations first. Then i removed it's(migrations i wanted to run) entry from django_migrationstable and ran migrations again(no fake this time).
我首先运行了假迁移。然后我从django_migrations表中删除了它的(我想运行的迁移)条目并再次运行迁移(这次不是假的)。
Changes appeared as expected for me.
变化出现在我的预期中。
hope this is helpful.
希望这是有帮助的。
回答by R.kiani
I found this problem in web2pyframework
in models/config.py
.
我web2pyframework
在models/config.py
.
Change
改变
settings.base.migrate = True
settings.base.migrate = True
on config file to
在配置文件上
settings.base.migrate = False
settings.base.migrate = False
Problem solved.
问题解决了。
回答by theeastcoastwest
Django provides a --fake-initial
option which I found effective for my use. From the Django Migration Documentation:
Django 提供了一个--fake-initial
我发现对我有用的选项。来自Django 迁移文档:
--fake-initial
Allows Django to skip an app's initial migration if all database tables with the names of all models created by all CreateModel operations in that migration already exist. This option is intended for use when first running migrations against a database that preexisted the use of migrations. This option does not, however, check for matching database schema beyond matching table names and so is only safe to use if you are confident that your existing schema matches what is recorded in your initial migration.
--fake-initial
如果迁移中的所有 CreateModel 操作创建的具有所有模型名称的所有数据库表已经存在,则允许 Django 跳过应用程序的初始迁移。此选项旨在在首次针对预先存在使用迁移的数据库运行迁移时使用。但是,此选项不会检查匹配表名称之外的匹配数据库架构,因此只有在您确信现有架构与初始迁移中记录的架构匹配时才可以安全使用。
For my use, I had just pulled a project from version control and was preparing to add some new model fields. I added the fields, ran ./manage.py makemigrations
and then attempted to run ./manage.py migrate
which threw the error since, as one would expect, many of the fields already existed in the existing database.
对于我的使用,我刚刚从版本控制中提取了一个项目,并准备添加一些新的模型字段。我添加了字段,./manage.py makemigrations
然后运行,然后尝试运行./manage.py migrate
,这引发了错误,因为正如人们所料,现有数据库中已经存在许多字段。
What I should have done was to run makemigrations
immediately after pulling the project from versions control to create a snapshot of existing models' state. Then, running the ./manage.py migrate --fake-initial
would be the next step.
我应该做的是makemigrations
在从版本控制中提取项目后立即运行以创建现有模型状态的快照。然后,运行./manage.py migrate --fake-initial
将是下一步。
After that you can add away and makemigrations
> migrate
as normal.
之后,您可以正常添加和makemigrations
> migrate
。
NOTE:I do not know if a --fake-initial
would skip existing fields andadd new ones. I opted to comment out the new fields I'd created up to that point, run the --fake-initial
as if it were the first thing I did after pulling from version control, thenadded in updated fields in the next migration.
注意:我不知道 a--fake-initial
是否会跳过现有字段并添加新字段。我选择注释掉到目前为止我创建的新字段,--fake-initial
就像我从版本控制中提取后所做的第一件事一样运行它,然后在下一次迁移中添加到更新的字段中。
Other related documentation: https://docs.djangoproject.com/en/dev/topics/migrations/#initial-migrations
其他相关文档:https: //docs.djangoproject.com/en/dev/topics/migrations/#initial-migrations
回答by max
I've been dealing with this for several years. There could be different scenarios:
我处理这个问题已经好几年了。可能有不同的场景:
Scenario 1: as in the original post, you had no tables to start with. In this case, I'd
场景 1:如在原始帖子中一样,您没有可以开始使用的表格。在这种情况下,我会
- comment out the relationship in models.py
- run python manage.py
- migrate assuming that it now succeeds
- uncomment what you
- commented out in step 1 run python manage.py migrate --fake
- 注释掉models.py中的关系
- 运行 python manage.py
- 迁移假设它现在成功
- 取消对你的评论
- 在步骤 1 中注释掉运行 python manage.py migrate --fake
Scenario 2: multiple apps: One possibility is that you might have different apps and the data model of one app is using some tables from the other app. In this case, if the data model is designed properly, you should be able to create the tables for one app only (by specifying only that one in setting.py), then add the other app and migrate. If it is not design with care, and there are recursive dependencies, I suggest changing the design rather than making a temporary fix.
场景 2:多个应用程序:一种可能性是您可能有不同的应用程序,并且一个应用程序的数据模型正在使用另一个应用程序的一些表。在这种情况下,如果数据模型设计正确,您应该能够仅为一个应用程序创建表(通过在 setting.py 中仅指定该表),然后添加另一个应用程序并迁移。如果不是精心设计,并且存在递归依赖关系,我建议更改设计而不是临时修复。
Scenario 3: you had some tables and something went wrong with your migration, then I'd
场景 3:你有一些表,你的迁移出了问题,然后我会
- revert models.py to what it was and only introduce the new relationship that appears to already exist in models.py.
- delete migration folder
- run python manage.py makemigrations
- introduce new changes to models.py if any and continue with makemigrations and migrate commands as usual.
- 将models.py恢复到原来的样子,只引入models.py中似乎已经存在的新关系。
- 删除迁移文件夹
- 运行 python manage.py makemigrations
- 如果有的话,向models.py 引入新的更改,并像往常一样继续执行makemigrations 和migrate 命令。