开发者

Using Django custom manager function on an already filtered queryset

Consider the following case:

class MyModelManager(models.Manager):
    def my_filter(self):
     return [some code here].filter(field_A__gt=3)

class MyModel(models.Model):
    # some fields
    objects = MyModelManager()


# The way I'd like to use it:
qs = MyModel.objects.filter(field_B__lt=1)
# some c开发者_JS百科ode
qs = qs.my_filter()

Notice that I'd like to use the custom my_filter() function on the already filtered queryset. What code should I place in the [some code here] above? Is the structure as a whole correct?


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


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(...)


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜