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 badges3 Answers
Reset to default 1Your 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 User
s, 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)