最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

how to delete OneToOneField of a model class in django - Stack Overflow

programmeradmin2浏览0评论

in my django app student_management_system, Student is connected to User by OneToOneField. if i delete a Student it gets deleted, but User (django's built in User) is not getting deleted, it still exists in database, ie. in auth_user of db.sqlite3. how to fix this. github code: the problem is also written in problem.txt there.

in my django app student_management_system, Student is connected to User by OneToOneField. if i delete a Student it gets deleted, but User (django's built in User) is not getting deleted, it still exists in database, ie. in auth_user of db.sqlite3. how to fix this. github code: https://github/anup30/student_management_system the problem is also written in problem.txt there.

Share Improve this question edited Mar 14 at 16:18 Anup Barua asked Mar 14 at 15:07 Anup BaruaAnup Barua 1036 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 1

Your code looks correct; on_delete=models.CASCADE should take care of that problem. Try overriding the delete() method on the Student model:

class Student(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    phone_number = models.CharField(max_length=15)
    courses = models.ManyToManyField(Course)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.user.first_name} {self.user.last_name}"

    def get_absolute_url(self):
        return reverse('student-detail', kwargs={'pk': self.pk})

    def delete(self, *args, **kwargs):
        self.user.delete()  # Delete related User
        super().delete(*args, **kwargs)

Remember run migrations to apply changes.

A OneToOneField model field [Django-doc] does not have bi-directional "triggers". So if you remove a User, it will remove the Student along with it, but if you remove a Student, you will not remove the User along with it.

It is thus actually more an "optional-to-one field": an optional Student linked to User so every Student has a User, but not every user has per se a Student.

You can implement override the .delete(…) [Django-doc] method of the Student model, as suggested, but this will not run when you delete in "bulk" so:

Student.objects.filter(pk__in=[1,4,2,5]).delete()

will not remove the corresponding Users, the same with signals.

If every user is a Student, it makes more sense to customize the user model [Django-doc], otherwise you can override .delete(), but with a scheduled that that regularly removes users without a student attached.

so, found 3 solutions for this problem, one suggested by Antonio Cruz, overriding delete method in Student model in models.py

def delete(self, *args, **kwargs):
        self.user.delete()  # Delete related User
        super().delete(*args, **kwargs)

another solution is using signals in models.py

from django.db.models.signals import post_delete
from django.dispatch import receiver

@receiver(post_delete, sender=Student)
def delete_user_when_student_deleted(sender, instance, **kwargs):
    instance.user.delete()

and instead of using the OneToOneField, we can use custom class inheriting AbstractUser/AbstractBaseUser. eg.

class CustomUser(AbstractUser):  # CustomUser class inherits from AbstractUser
    age = models.PositiveIntegerField(null=True, blank=True)
发布评论

评论列表(0)

  1. 暂无评论