更改ForeignKey的Django IntegrityError

时间:2018-03-30 20:32:54

标签: python django database postgresql

我有一个模型LucyGuide,它通过User扩展了Django的OneToOneField模型:

class LucyGuide(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)

还有一个Company模型,其中有一个名为lucy_guide的字段,它是ForeignKey模型的User

class Company(models.Model):
    lucy_guide = models.ForeignKey(User)

我想将此更改为

class Company(models.Model):
    lucy_guide = models.ForeignKey(LucyGuide)

但是,当我实施此更改并制作和运行迁移时,我遇到了IntegrityError

django.db.utils.IntegrityError: insert or update on table "lucy_web_company" violates foreign key constraint "lucy_web_company_lucy_guide_id_de643702_fk_lucy_web_"
DETAIL:  Key (lucy_guide_id)=(461) is not present in table "lucy_web_lucyguide".

这个问题类似于IntegrityError Insert or update on table "orders_order" violates foreign key constraint ";好像我在引用它们作为外键之前创建了LucyGuide个对象。

解决此问题的最佳方法是什么?我需要在shell中编写一系列命令来创建这些用户吗?

更新

从shell中查看,似乎Django仍然期望id具有相同的数字ForeignKey,即使模型已更改(从User更改为{{1 }})。以下LucyGuide ids也是User s:

LucyGuide

请注意,这包含错误中的In [11]: lucy_guide_users = [user for user in User.objects.all() if hasattr(user, 'lucyguide')] In [16]: [user.id for user in lucy_guide_users] Out[16]: [12, 8, 461, 497, 500, 471, 475, 495] id。然而,461的{​​{1}}只是

id

似乎解决这个问题的方法是更改​​LucyGuide的主键,但似乎What is the best approach to change primary keys in an existing Django app?这是一个非常复杂的过程。有更简单的方法吗?

1 个答案:

答案 0 :(得分:1)

您不能简单地更改外键的目标。对于每个现有公司,您需要将lucy_guide_id从相关用户的ID更改为相关的lucy_guide的ID。 Django不能为你做这件事。

您可以通过几个步骤进行迁移。首先,添加一个新的外键并创建一个迁移

class Company(models.Model):
    lucy_guide = models.ForeignKey(User)
    new_lucy_guide = models.ForeignKey(LucyGuide, blank=True, null=True)

接下来,创建data migration以填充new_lucy_guide字段。

然后,您可以删除lucy_guide字段,然后创建迁移。

class Company(models.Model):
    new_lucy_guide = models.ForeignKey(LucyGuide, blank=True, null=True)

最后,您可以重命名字段并创建迁移:

class Company(models.Model):
    lucy_guide = models.ForeignKey(LucyGuide, blank=True, null=True)

你可能能够在一次迁移中完成最后两个步骤,我记不清了。