可以在 Django 中执行条件 ForeignKey.on_delete 吗?

Posted

技术标签:

【中文标题】可以在 Django 中执行条件 ForeignKey.on_delete 吗?【英文标题】:Possible to do conditional ForeignKey.on_delete in Django? 【发布时间】:2013-01-25 11:45:33 【问题描述】:

通过on_delete option, Django provides various alternatives 了解如何处理具有正在删除的对象的外键的对象。

我想知道是否有办法可以做类似的事情,但有条件。这是场景。我正在使用 Django 1.5 的新自定义用户模型,并且我的所有用户都有一个外键到站点。像这样:

class TenantSiteUser(AbstractUser):
  site = models.ForeignKey(Site, null=True)

如果一个站点被删除,那么我宁愿删除所有链接到该站点的非超级用户(即类似 KASKADE 的行为),因为它们的存在现在毫无意义。但是,如果它是超级用户,我宁愿将用户的站点设置为 null(即 SET_NULL)并让它们保持存在,因为这可能是我或与我一起工作的人,我们往往不想无意中删除自己。

我可以重写什么来手动检查并实现这种类型的 on_delete 行为吗?

编辑:这是最终为我工作的代码,基于@Kevin 的回答和对现有处理程序如何工作的一些研究:

def NULLIFY_SUPERUSERS_ELSE_CASCADE(collector, field, sub_objs, using):
    superusers = []
    for user in sub_objs:
        if user.is_superuser:
            sub_objs = list(sub_objs)
            sub_objs.remove(user)
            superusers.append(user)

    CASCADE(collector, field, sub_objs, using)
    if len(superusers):
        collector.add_field_update(field, None, superusers)

class TenantSiteUser(AbstractUser):
    site = models.ForeignKey(Site, null=True, on_delete=NULLIFY_SUPERUSERS_ELSE_CASCADE)

【问题讨论】:

工作就像一个魅力。谢谢! 【参考方案1】:

Django 提供的选项(CASCADEPROTECT 等)都是函数 - here's where they're defined 用于 1.5。

我还没有测试过,但应该可以编写自己的 NULL_OR_CASCADE 函数并将其作为字段的 on_delete 参数传递。

【讨论】:

效果很好!甚至不觉得自己像个黑客。非常感谢。

以上是关于可以在 Django 中执行条件 ForeignKey.on_delete 吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Django 项目中使用 sweetpie 将多个对象保存在同一模型中

Django--分页功能

ForeignK优解 [堆]

Django:如何创建类别字段/下拉菜单?

Django:管理员中的 AJAX/jQuery

ListView中的Django过滤关系