首页 > 解决方案 > Django 模型外键 on_delete=null 但外键还是被删除了

问题描述

我正在尝试将删除值上的外键引用从级联更改为 null,如下所示:

created_by = models.ForeignKey(CustomUser,on_delete=models.SET_NULL, null=True)

当我通过从 CustomUser 中删除记录来测试这一点时,我会在执行删除之前和之后获得 Games 表中对象的计数。

p = Games.objects.count()
print(p) #outputs 100
print(Games.objects.filter(created_by=2)) #outputs <QuerySet [<Games: 181 79 None>]>

cu = CustomUser.objects.get(pk=2)
cu.delete()

p = Games.objects.count()
print(p) #outputs 98
print(Games.objects.filter(created_by=2)) # outputs <QuerySet []>

我尝试使用其他值进行删除,但唯一不从数据库中删除行的值是保护。相反,它会引发保护错误

 raise ProtectedError(
django.db.models.deletion.ProtectedError: ("Cannot delete some instances of model 'CustomUser' because they are referenced through a protected foreign key: 'Games.created_by'", <QuerySet [<Games: 181 79 None>]>)

CustomUser 和 Games 模型的代码

class CustomUser(AbstractBaseUser, PermissionsMixin):
    id = models.BigAutoField(primary_key=True)
    username = models.CharField(max_length=15, unique=True)
    email = models.EmailField(max_length=128, unique=True)
    password = models.CharField(max_length=254)
    salt = models.CharField(max_length=128)
    email_verified = models.BooleanField(default=False)
    avatar = models.ImageField(blank=True, null=True)
    date_joined = models.DateTimeField(default=timezone.now)
    last_updated = models.DateTimeField(blank=True, null=True)
    is_active = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'
    objects = CustomUserManager()

    def __str__(self):
        return self.email



class Games(models.Model):
    CATEGORY = (
        ('general knowledge','general knowledge'),
        ('science','science'),
        ('mythology','mythology'),
        ('sports','sports'),
        ('geography','geography'),
        ('history','history'),
        ('politics','politics'),
        ('art','art'),
        ('celebrities','celebrities'),
        ('animals','animals'),
        ('vehicles','vehicles'),
        ('entertainment','entertainment'),
        ('random','random')
    )

    id = models.BigAutoField(primary_key=True)
    number_of_questions = models.SmallIntegerField()
    number_of_players = models.SmallIntegerField()
    start_time = models.DateTimeField(default=timezone.now)
    category = models.CharField(max_length=18, choices=CATEGORY)
    created_by = models.ForeignKey(CustomUser,on_delete=models.SET_NULL, null=True)
    result_id = models.ForeignKey(Results, on_delete=models.CASCADE, null=True, blank=True)
    sudden_death_id = models.ForeignKey(SuddenDeath, on_delete=models.CASCADE, null=True, blank=True)

    objects = models.Manager()

    def __str__(self):
        return '%s %s %s' % (self.id, self.result_id, self.sudden_death_id)

标签: djangodjango-models

解决方案


我曾经django-extensions reset_db重置我的数据库,删除了所有迁移并重新运行。makemigrations&migrate从我的灯具中导入相同的数据集后,我再次运行了这段代码

        p = Games.objects.count()
        print(p) #output 100
        print(Games.objects.filter(created_by=2)) # output <QuerySet [<Games: 181 79 None>]>
        cu = CustomUser.objects.get(pk=2)
        cu.delete()
        p = Games.objects.count()
        print(p) #output 100
        print(Games.objects.get(pk=181)) #output 181 79 None

这证实了外键行没有被删除。

我将此标记为已接受的答案,但如果有人能够解释如何在不重置数据库的情况下解决问题,我会将其标记为已接受的答案。


推荐阅读