How to use custom managers in chain queries?

I159 picture I159 · Sep 18, 2011 · Viewed 7.3k times · Source

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?

Answer

zzart picture zzart · Nov 17, 2012

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