How to delete delete OneToOneField of a model class in django

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.com/anup30/student_management_system the problem is also written in problem.txt there.

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 2 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()
Back to Top