tak*_*kje 0 python django postgresql django-migrations
我有两个 Django(外键)字段 - FieldA 和 FieldB - 引用同一个类,但是不同的对象。然后我想将 FieldB 重命名为 FieldC。我在一次迁移中重命名了它(自动检测)。
然后我意识到我实际上需要一个与旧 FieldB 同名的新字段(也是同一类的外键)。因此,我创建了第二个迁移来添加新字段:FieldB。由于我刚刚重命名了另一个,我认为这不会给数据库带来任何问题。
我在本地使用 SQLite DB 进行开发,效果很好。当我将其推送到我们的 Postgres 数据库时,这返回了一个错误。
模型类
class ModelClass(Model):
field_a: ForeignClassA = models.ForeignKey(ForeignClassA, on_delete=models.SET_NULL, blank=True, null=True, related_name='FieldA')
# this one should be renamed to field_c after which I create another field with the same name and properties.
field_b: ForeignClassA = models.ForeignKey(ForeignClassA, on_delete=models.SET_NULL, blank=True, null=True, related_name='FieldB')
Run Code Online (Sandbox Code Playgroud)
迁移一:重命名
operations = [
migrations.RenameField(
model_name='modelname',
old_name='FieldB',
new_name='FieldC',
),]
Run Code Online (Sandbox Code Playgroud)
迁移二:添加字段
operations = [
migrations.AddField(
model_name='modelname',
name='FieldB',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='FieldB', to='app.othermodel'),
),]
Run Code Online (Sandbox Code Playgroud)
当我运行此迁移时,出现以下错误
Applying app.xxx1_previous... OK
Applying app.xxx2_rename_field... OK
Applying app.xxx3_add_field...Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.DuplicateTable: relation "app_modelname_fieldB_id_8c448c6a" already exists
Run Code Online (Sandbox Code Playgroud)
通常该列应被删除并替换为具有新名称的新列。我发现这个问题描述了 Postgress 中的类似问题,现在我想知道这是否是 Django 中的错误。难道是重命名后的清理工作没有正确完成?
仔细检查 Postgres DB 后,我可以看到,重命名后,我的表中仍然有两列:FieldA_id 和 FieldB_id,而我希望有 FieldA_id 和 FieldC_id。显然,如果我随后尝试再次添加 FieldB,这会产生问题。
难道 Postgres(或 Django 控制器)由于某种原因没有重命名该列?
我检查了对 Postgres 数据库的 SQL 查询。生成以下 SQL:
Applying app.xxx1_previous... OK
Applying app.xxx2_rename_field... OK
Applying app.xxx3_add_field...Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.10/site-packages/django/db/backends/utils.py", line 85, in _execute
return self.cursor.execute(sql, params)
psycopg2.errors.DuplicateTable: relation "app_modelname_fieldB_id_8c448c6a" already exists
Run Code Online (Sandbox Code Playgroud)
然而,此重命名似乎仅部分执行,因为下一步报告了问题,但迁移成功了。
但是,当我手动运行此 SQL 查询时,该命令成功并且升级部分成功。总之:
经过长时间的 SQL 兔子洞搜索后,我发现 PostgresQL 的重命名迁移不会删除旧索引。
当我想创建一个新字段时,它尝试创建一个与旧索引(未删除)同名的新索引。
避免这种情况的一个简单方法是将重命名与两个更改操作“夹在中间”。一种是取消设置索引,另一种是在之后将其设置回来。
operations = [
migrations.AlterField(
model_name='modelclass',
name='field_b',
field=models.ForeignKey(blank=True, db_index=False, null=True, on_delete=django.db.models.deletion.SET_NULL,
to='otherapp.otherclass'),
),
migrations.RenameField(
model_name='modelclass',
old_name='field_b',
new_name='field_c',
),
migrations.AlterField(
model_name='modelclass',
name='field_c',
field=models.ForeignKey(blank=True, db_index=True, null=True, on_delete=django.db.models.deletion.SET_NULL,
to='otherapp.otherclass'),
),
]
Run Code Online (Sandbox Code Playgroud)
我也在 Django bug tracker 上报告了这个问题,之后他们关闭了它,因为7 年前就存在重复的问题。
归档时间: |
|
查看次数: |
1966 次 |
最近记录: |