Django:外键 on_delete SET_DEFAULT 行为

0x2*_*207 2 django

让我考虑以下两个模型:

class Policy(models.Model):
        name = models.SlugField(max_length=256, blank = False, unique = True)
def default_policy():
        return Policy.objects.get(name='default').pk
class Item(models.Model):
        policy = models.ForeignKey('Policy', on_delete=models.SET_DEFAULT, default=default_policy)
Run Code Online (Sandbox Code Playgroud)

除了一个操作外,一切都按预期工作。我仍然可以毫无例外地执行以下操作:

p = Policy.objects.get(name='default')
p.delete()
Run Code Online (Sandbox Code Playgroud)

这会产生孤立的Items,它们指的是“默认”Policy对象。不幸的是,此操作导致数据库中的完整性问题,因为现在有Item哪些 policy_id 列指的是Policy表的丢失记录。

我怎样才能防止这种情况发生?Policy当没有Items 指代它时删除“默认”对我来说是可以接受的。

dir*_*ten 5

这取决于您的业务需求。每个Item都应该总是指向一个有效的Policy吗?当 aPolicy被删除时,从业务角度来看有什么要求?Item指向它的s 也应该删除吗?我们不知道您的要求,因此很难回答您的问题。从技术角度来看,这些是您的选择:

  • 设置on_delete=CASCADE是否要在Item删除时Policy删除
  • on_delete=PROTECT如果Policy仍然有任何Item指向它,则设置是否不允许删除任何内容。在这种情况下,您必须try: policy.delete(); except ProtectedError: ...在代码中处理这种情况。
  • 设置on_delete=SET_DEFAULT,如果你知道你的默认策略将不会被删除(你可以重写delete的方法Policy,以避免删除默认策略)。
  • 设置on_delete=SET_NULL是否Item可以没有Policy。这在某些业务场景中可能是有效的。但在这种情况下,您还必须拥有null=True.