与用户模型(django.contrib.auth)的OneToOne关系,没有级联删除

时间:2011-08-05 22:26:15

标签: django django-authentication one-to-one cascading-deletes

我对删除发挥作用时OneToOneField的工作方式感到有些困惑。我能找到的唯一准权威信息来自this thread on django-developers

  

我不知道你是否发现了这个,但删除工作正在进行中   一个方向,但不是你期望它的方向。对于   例如,使用您在另一条消息中发布的模型:

class Place(models.Model): 
    name = models.CharField(max_length = 100)  
class Restaurant(models.Model): 
    place = models.OneToOneField(Place, primary_key=True)  
     

如果你   创建一个与其链接的地方和餐厅,删除   餐厅不会删除地方(这是你的问题   报告此处),但删除地方将删除餐厅。

我有以下型号:

class Person(models.Model):
    name = models.CharField(max_length=50)
    # ... etc ...
    user = models.OneToOneField(User, related_name="person", null=True, blank=True)

这是以这种方式设置的,因此我可以使用personUser实例轻松访问user.person

然而,当我尝试删除管理员中的User记录时,它自然会向后传递到我的Person模型,就像讨论的主题一样,显示了以下内容:

您确定要删除用户“JordanReiter2”吗?以下所有相关项目都将被删除:

  • 用户:JordanReiter
    • 人:JordanReiter
      • 提交:Title1
      • 提交:Title2

不用说我想要删除Person记录或其任何后代!

我想我理解逻辑:因为Person记录中的OneToOne字段中有一个值,删除User记录会在数据库的user_id列中创建一个错误的引用。

通常,解决方案是切换OneToOne字段所在的位置。当然,这并不现实,因为User对象几乎由django.contrib.auth设置。

是否有任何方法可以阻止删除级联,同时仍然可以通过简单的方式从user访问此人? 方式是否可以创建扩展User版本的django.contrib模型?

更新

我改变了模型名称,所以希望现在它更清晰了。基本上,有成千上万的人事记录。不是每个人都有登录,但如果他们这样做,他们只有一个登录。

2 个答案:

答案 0 :(得分:23)

原来你可以将ForeignKey and OneToOneField have an attribute on_delete设置为models.SET_NULL,如下所示:

class Person(models.Model):
    name = models.CharField(max_length=50)
    # ... etc ...
    user = models.OneToOneField(User, on_delete=models.SET_NULL, related_name="person", null=True, blank=True)

这会导致我想要的行为:删除User模型而不触及Person记录。我忽略了它,因为它没有在OneToOneField下明确列出,只是说

  

此外,OneToOneField接受ForeignKey接受的所有额外参数......

容易错过。

答案 1 :(得分:0)

对于此用例,您应该使用简单的ForeignKey。 OneToOne意味着有一个,只能是一个,它只能与这一个特定的其他对象相关联。删除的原因是因为有一个空的onetoone字段是没有意义的,它不能与其他任何东西相关联。