I have a setup like this (simplified for this question):
class Employee(models.Model):
name = models.CharField(name, unique=True)
class Project(models.Model):
name = models.CharField(name, unique=True)
employees = models.ManyToManyField(Employee)
When an Employee is about to get deleted, I want to check whether or not he is connected to any projects. If so, deletion should be impossible.
I know about signals and how to work them. I can connect to the pre_delete
signal, and make it throw an exception like ValidationError
. This prevents deletion but it is not handled gracefully by forms and such.
This seems like a situation that other will have run into. I'm hoping someone can point out a more elegant solution.
I was looking for an answer to this problem, was not able to find a good one, which would work for both models.Model.delete() and QuerySet.delete(). I went along and, sort of, implementing Steve K's solution. I used this solution to make sure an object (Employee in this example) can't be deleted from the database, in either way, but is set to inactive.
It's a late answer.. just for the sake of other people looking I'm putting my solution here.
Here is the code:
class CustomQuerySet(QuerySet):
def delete(self):
self.update(active=False)
class ActiveManager(models.Manager):
def active(self):
return self.model.objects.filter(active=True)
def get_queryset(self):
return CustomQuerySet(self.model, using=self._db)
class Employee(models.Model):
name = models.CharField(name, unique=True)
active = models.BooleanField(default=True, editable=False)
objects = ActiveManager()
def delete(self):
self.active = False
self.save()
Usage:
Employee.objects.active() # use it just like you would .all()
or in the admin:
class Employee(admin.ModelAdmin):
def queryset(self, request):
return super(Employee, self).queryset(request).filter(active=True)