[Django]-Using Django custom manager function on an already filtered queryset

2👍

I guess there is no way to do it exactly this way.
MyModel.objects.filter(field_B__lt=1)
will return QuerySet object, not MyModelManager.
You may either pass it to my_filter method as Ignacio Vazquez-Abrams mentioned or first apply my_filter to your manager, that will return QuerySet object, that you can filter further

1👍

Your approach is wrong because you can only use Model.Manager while you retreive data from database, so using two managers or trying to use a manager ona a queryset causes error.

data = SomeModel.objects.my_manager.all()

or

data = SomeModel.objects.all()
data = data.my_manager.filter(...)

is wrong since you can not use two managers…

One possible waw is defining a function that gets a queryset as a parameter and returns a filtered queryset…

def extra_filter(queryset):
    queryset = queryset.filter(...)

but i am not sure if this helps.

Best approach is defining another model Manager and use it instread of objects if required…

class SomeManager(models.Manager):
    def get_query_set(self):
        return super(SomeManager, self).get_query_set().filter(<filteer criteria>)

class MyModel(models.Model):
    # some fields
    objects = models.Manager()
    mymanager = SomeManager()

data = MyModel.mymanager.all() 

And use just one…

UPDATE: In django, querysets are lazy. That means, you can apply as many filters as you wish and data will not be retreived from the database unliess you try to get a specific record from the filtered or you try to slice it…Documentation is here

So, there is no diffrence between

qs = MyModel.objects.filter(field_B__lt=1)
qs = qs.filter(field_A__gt=3)

and

qs = MyModel.objects.filter(field_A__gt=3)
qs = qs.filter(field_B__lt=1)

So defining a manager to apply a specific filtering is the main reason for using managers…

You define your manager :

class SomeManager(models.Manager):
    def get_query_set(self):
        return super(SomeManager, self).get_query_set().filter(field_A__gt=3)

then you call it with other filtering criteria:

Somemodel.mymodelmanager.filter(field_B__lt=1, ....)

And django will add all filters and evluate the query when you want it to do.

So if it is a filter that you use oftenly, manager i the best choice…

As for an example, i have valid_ field in my most database models and a val manager that filters invalid entries. So When i wish to filter all valid data (90% of the time) i use

Somemodel.val.filter(...)

And in the situation that i need all the data i just use basic django manager:

Somemodel.objects.filter(...)
👤Mp0int

0👍

class MyModelManager(models.Manager):
    def my_filter(self, qs=None):
        if qs is None:
            qs = [however you got it before]
        return qs.filter(field_A__gt=3)

Then just pass your queryset to it.

Leave a comment