删除PROTECTED ForeignKey下的自动创建的模型

时间:2015-08-11 18:57:19

标签: python django foreign-key-relationship

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)

...

myapple = new Apple(name="my")
myapple.save()

...

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

我尝试将auto_created_basket换成另一个,但是当我尝试删除它时出错。

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

3 个答案:

答案 0 :(得分:2)

basket模型中,basket = models.ForeignKey(Basket, on_delete=models.PROTECT) 字段是外键

on_delete

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

正如official docs所说

  

删除ForeignKey引用的对象时,Django by   default模拟SQL约束ON DELETE CASCADE的行为   并删除包含ForeignKey的对象。

  

PROTECT参数可防止通过引发删除引用的对象   ProtectedError

因此,最简单的步骤应该是删除basket = models.ForeignKey(Basket) 参数并使用默认行为

{{1}}

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

答案 1 :(得分:1)

您可以尝试将苹果从auto_created_basket移至existing_basket,然后再删除购物篮:

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

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

或者,如果您想在一个购物篮中收集来自已删除购物篮的苹果,您可以将功能分配给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')

答案 2 :(得分:1)

我讨厌回答我的问题,但我的例子太简单了。答案非常好。

在真实产品中,涉及post_save信号,负责创建auto_created_basket

问题在于,当我说myapple.basket = existing_basket Django的图层很好,但DB仍然保留对较旧关系的引用。我的解决方案是在我再次保存auto_created_basket.delete()后移动myapple