将多处字段更改为外键时,Django迁移错误

时间:2018-09-09 07:05:02

标签: python django postgresql

最初,我的models.py看起来很喜欢

class P (models.Model):
    first_name=models.CharField(max_length=100);

    def __str__(self):
        return self.first_name

class T (models.Model):
    p_id=models.ManyToManyField(P)

一切正常。然后我将T类更改如下:

class T (models.Model):
        p_id=models.ForeignKey(P,on_delete=models.CASCADE,default=None,null=True)
#I have added default values coz django asks me to during migrations

我收到以下错误:

django.db.utils.ProgrammingError: column "p_id_id" does not exist

以前,当发生此类错误时,我曾经从Postgresql DB中删除所有表,然后在我的应用程序中注释掉了整个models.py,运行了一个伪造的迁移,然后取消对models.py的注释,然后再次运行迁移,这样就可以了。但这会破坏数据库中的所有数据。有没有一种方法可以使它在不删除任何数据的情况下起作用?

1 个答案:

答案 0 :(得分:0)

我在问题中谈论的错误可能是因为我在models.py中使用p_id进行了伪迁移,就像FK那样,它告诉Django DB中已经存在p_id_id,只是创建一个迁移文件。当我从头开始尝试所有内容而不进行假迁移时,错误消失了。

Django不会自动将m2m更改为FK(一对多),这很有意义。如果将m2m更改为FK后运行迁移,则映射表appname_t_p会被删除,并且数据将永远丢失。我做了以下的事,并且奏效了:

在m2m“ appname_t_p”期间创建的手动备份映射表。

create table atp as select * from appname_t_p;

在models.py中将m2m更改为FK(如问题所示)。然后进行迁移(不是假迁移)。这会在T表中创建一个新的全空列p_id_id。

然后手动编写sql更新语句,以将来自备份表atp的值添加到表appname_t的p_id_id(所有NULLS)列中。

UPDATE appname_t t1
SET    p_id_id = t2.p_id
FROM   atp t2
WHERE  t2.t_id = t1.id;

然后验证值,这是正确的。

相关问题