Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use custom managers in chain queries?

I made a custom manager that has to randomize my query:

class RandomManager(models.Manager):

    def randomize(self):        
        count = self.aggregate(count=Count('id'))['count']
        random_index = random.randint(0, count - 1)
        return self.all()[random_index]

When I use the method defined in my manager in the first place, it's works ok:

>>> PostPages.random_objects.randomize()
>>> <PostPages: post 3>

I need to randomize the already filtered query. When I tried to use the manager and the method in chain I got an error:

PostPages.random_objects.filter(image_gallary__isnull=False).randomize()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/home/i159/workspace/shivaroot/shivablog/<ipython-input-9-98f654c77896> in <module>()
----> 1 PostPages.random_objects.filter(image_gallary__isnull=False).randomize()

AttributeError: 'QuerySet' object has no attribute 'randomize'

Result of filtering is not an instance of model class, but it's django.db.models.query.QuerySet, so that it does not have my manager and method, respectively. Is there a way to use custom manager in chain query?

like image 482
I159 Avatar asked Sep 18 '11 11:09

I159


People also ask

Why might you want to write a custom model Manager?

Custom managers. You can use a custom Manager in a particular model by extending the base Manager class and instantiating your custom Manager in your model. There are two reasons you might want to customize a Manager : to add extra Manager methods, and/or to modify the initial QuerySet the Manager returns.

Where are model managers used?

It is used to get queryset of objects based on the properties it takes as arguments. If no argument is provided then it will return all the objects. In this example, we create a custom django manager by inheriting Manager class and overriding only the get_queryset method .

What does Models Manager class do?

A Manager is a Django class that provides the interface between database query operations and a Django model. In other words, in a Django model, the manager is the interface that interacts with the database.

What is Model Manager?

Model Manager is a web application that allows users to login to a Modeler server and perform common database and model management tasks on that Modeler Server. Executing tasks on the Modeler Server, instead of the Modeler Client, significantly improves performance of many operations.


2 Answers

This is how you chain custom methods on custom manager ie: Post.objects.by_author(user=request.user).published()

from django.db.models.query import QuerySet

class PostMixin(object):
    def by_author(self, user):
        return self.filter(user=user)

    def published(self):
        return self.filter(published__lte=datetime.now())

class PostQuerySet(QuerySet, PostMixin):
    pass

class PostManager(models.Manager, PostMixin):
    def get_query_set(self):
        return PostQuerySet(self.model, using=self._db)

Link here : django-custom-model-manager-chaining

Note :

In Django 1.7 you have this out of the box . Check out QuerySet.as_manager

like image 175
zzart Avatar answered Oct 28 '22 10:10

zzart


Just a code example using the new as_manager() method (see update information from @zzart.

class MyQuerySet(models.query.QuerySet):
    def randomize(self):        
        count = self.aggregate(count=Count('id'))['count']
        random_index = random.randint(0, count - 1)
        return self.all()[random_index]

class MyModel(models.Model):
    .....
    .....
    objects = MyQuerySet.as_manager()
    .....
    .....

And then you will be able to use something like this in your code:

MyModel.objects.filter(age__gt=16).randomize()

As you can see, the new as_manager() is really neat:)

like image 30
Zhe Li Avatar answered Oct 28 '22 12:10

Zhe Li