Edgar Navasardyan
Edgar Navasardyan

Reputation: 4501

Django - combining custom querysets used as managers with abstract class inheritance

Basically, I have to achieve two goals in my project that are currently conflicting with each other in terms of implementation.

The goals are:

  1. Enabling chainable filtering for model instances (my_model.objects.custom_filter1().custom_filter2() etc)
  2. For those tables with is_deleted field, and I want to exclude records marked as deleted, so that I don't have to explicitly filter for deleted records (use my_model.objects.all() instead of my_model.objects.filter(is_deleted = false))

Currently I have the following code:

class MixinManager(models.Manager): 
    def get_queryset(self):
        try:
            return self.model.MixinQuerySet(self.model).filter(is_deleted=False)
        except FieldError:
            return self.model.MixinQuerySet(self.model)

class BaseMixin(models.Model):
    objects = MixinManager()

class MixinQuerySet(QuerySet):
    pass
    class Meta:
       abstract = True

class DeleteMixin(BaseMixin):
    is_deleted = models.BooleanField(default=False)

    class Meta:
        abstract = True

class Sms(DeleteMixin):
    # core fielrds
    # objects = SmsQuerySet.as_manager()
    class Meta:
        managed = False
        db_table = 'sms'

However, my first goal becomes seemingly infeasible. Prior to using abstract classes for achieving the second goal, I had the following code to solve the second goal:

class SmsQuerySet(models.query.QuerySet):
    def filter_1(self, user):
        return self.filter(...)
    def filter_2(self, user):
        return self.filter(...)

    def filter_3(self, user):
        return self.filter(...)

class Sms(models.Model):
   # core fields
   objects = SmsQuerySet.as_manager()

This syntax solved my first goal.

THE QUESTION:

The problem is that I can't combine these two structures into one logic, so that I can write:

sms.objects.filter_1().filter_2().filter_3()

so that deleted records are exluded from sms.objects. If I uncomment the # objects = SmsQuerySet.as_manager() line in the first code snippet, then the objects field of BaseMixin will be ignored and I will end up with deleted records in the final queryset. On the other hand, if I comment the line, than my custom querysets become unreachable.

I hope I succeeded to concisely describe what I am trying to do. Will be very grateful for any hint towards the solution!

Upvotes: 2

Views: 1135

Answers (1)

Anton Perepelitcyn
Anton Perepelitcyn

Reputation: 515

It should work

from django.db import models

class SmsQuerySet(models.query.QuerySet):
    def filter_1(self, user):
        return self.filter(...)
    def filter_2(self, user):
        return self.filter(...)

    def filter_3(self, user):
        return self.filter(...)


class MixinManager(models.Manager): 
    def get_queryset(self):
        try:
            return SmsQuerySet(self.model).filter(is_deleted=False)
        except FieldError:
            return SmsQuerySet(self.model)


class Sms(models.Model):
   # core fields
   objects = MixinManager()

Upvotes: 1

Related Questions