删除受保护的外键下自动创建的模型

Csa*_*oth 7 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)
Run Code Online (Sandbox Code Playgroud)

...

myapple = new Apple(name="my")
myapple.save()
Run Code Online (Sandbox Code Playgroud)

...

auto_created_basket = myapple.basket
myapple.basket = existing_basket
auto_created_basket.delete()
Run Code Online (Sandbox Code Playgroud)

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

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

Pyn*_*hia 7

在您的Apple模型中,该basket字段是外键

basket = models.ForeignKey(Basket, on_delete=models.PROTECT)
Run Code Online (Sandbox Code Playgroud)

on_delete属性值明确规定通过防止删除篮子来保护苹果,即只要篮子里还有苹果就不能删除。

正如官方文档所说

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

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

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

basket = models.ForeignKey(Basket)
Run Code Online (Sandbox Code Playgroud)

但是,请查看外键模型字段的所有可能参数,并选择适合您的应用程序/场景要求的组合。

更新:

最近的 Django 版本需要on_delete. 只是不要删除它并添加您想要的参数(例如on_delete=models.CASCADE)。

  • 只是一个快速评论,因为这个答案在谷歌上排名相当高,并且包含逻辑错误:“on_delete”没有指定在删除“Basket”时不应删除“Apple”:相反,它指定“Basket”只要“Apple”仍在其中,就无法删除。您的官方文档引用也表明,上面的解释与之相矛盾:-) - 否则是很好的答案 (2认同)

Csa*_*oth 2

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

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

问题是,当我说myapple.basket = existing_basketDjango 的层很好时,但数据库仍然保留对旧关系的引用。我的解决方案是在再次auto_created_basket.delete()保存后移动。myapple