Ibolit
Ibolit

Reputation: 9720

Django: extend QuerySet with a default filter

I'm trying to implement a soft-delete model in my project. To that end, I want to be able to filter out deleted objects by default.

At the same time, I want to keep all my QuerySet filters in one place and accessible as MyModel.objects. I also want to be able to chain my filtering methods, so I'm looking towards using MyQuerySet.as_manager() as the manager for such models.

Thus it looks like I need to extend Django's QuerySet, but add a custom default filter. However, I can't figure out how to do that.

The following code does not look like a great idea.

class MyQuerySet(models.QuerySet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self = self.filter(deleted=False)

I also tried to figure out how to use Manager.from_queryset() for that purpose, but I still don't see how to make a manager that would be reusable, that is one that I could inherit from and be able to add my own QuerySet methods and still have the default filtering.

Upvotes: 0

Views: 1626

Answers (1)

Hari
Hari

Reputation: 1623

Let's start by creating a custom manager

class SoftDeleteManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(deleted=False)

Create Custom Queryset to add custom queryset methods.

class SoftDeleteQuerySet(models.QuerySet):
    def soft_delete(self):
         return self.update(deleted=True)

class CarQuerySet(SoftDeleteQuerySet):
      def with_color(self):
          pass

In your model

class CarModel(models.Model):
     all_objects = models.Manager()
     objects =  SoftDeleteManager.from_queryset(CarQuerySet)()

Upvotes: 2

Related Questions