正在删除受ForeignKey保护的自动创建的模型

2024-05-06 09:39:48 发布

您现在位置:Python中文网/ 问答频道 /正文

class Basket:
    name = models.CharField(max_length=50, blank=True, null=True)

class Apple:
    name = models.CharField(max_length=50, blank=True, null=True)
    basket = models.ForeignKey(Basket, on_delete=models.PROTECT)

。。。在

^{pr2}$

。。。在

auto_created_basket = myapple.basket
myapple.basket = existing_basket
auto_created_basket.delete()

我试着把自动创建的篮子换成另一个篮子,但是当我试图删除它时,我得到了一个错误。在

"Cannot delete some instances of model 'Basket' because they are referenced through a protected foreign key: 'Apple.basket'", [<Apple: My apple>])


Tags: nametrueappleautomodelsdeletenulllength
3条回答

在您的Apple模型中,basket字段是一个foreeng键

basket = models.ForeignKey(Basket, on_delete=models.PROTECT)

on_delete属性明确指出,当苹果所在的篮子被删除时,不应删除这些苹果。在

正如official docs所说

When an object referenced by a ForeignKey is deleted, Django by default emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey.

以及

the PROTECT parameter prevents deletion of the referenced object by raising ProtectedError

因此,最简单的步骤应该是删除on_delete参数并使用默认行为

^{pr2}$

但是请查看ForeignKey model field的所有可能参数,并选择适合您的应用程序/场景要求的组合。在

在删除篮子之前,可以尝试将苹果从auto_created_basket移到existing_basket中:

>>> auto_created_basket.apple_set.update(basket=existing_basket)
>>> auto_created_basket.delete()

或者

^{pr2}$

或者,如果要收集单个篮子中已删除篮子中的苹果,可以将函数分配给on_delete属性,如下所示:

def get_sentinel_basket():
    basket, created = Basket.objects.get_or_create(name='DELETED')
    return basket

basket = models.ForeignKey(Basket, on_delete=models.SET(get_sentinel_basket))

所以当一个篮子被删除时,篮子里苹果的.basket属性将自动设置为Basket(name='DELETED')。在

我不想回答我的问题,但我的例子过于简化。答案是非常好的。在

在实际产品中,涉及post_save信号,例如负责auto_created_basket的创建。在

问题是,当我说myapple.basket = existing_basketDjango的层是好的,但是DB仍然保留对旧关系的引用。在我的例子中,解决方案是在我再次保存myapple之后移动{}。在

相关问题 更多 >