Login

Custom Model Manager Chaining

Author:
hunterford
Posted:
July 19, 2010
Language:
Python
Version:
1.1
Tags:
orm manager queryset
Score:
4 (after 4 ratings)

Using Python mixins, you can chain methods on your queryset.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from datetime import datetime

from django.db import models
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)

class Post(models.Model):
    user = models.ForeignKey(User)
    published = models.DateTimeField()

    objects = PostManager()

Post.objects.by_author(user=request.user).published()

More like this

  1. Easier custom Model Manager Chaining by gsakkis 4 years, 7 months ago
  2. Custom managers with chainable filters by itavor 7 years, 1 month ago
  3. Chain multiple querysets into one by mattdw 6 years, 5 months ago
  4. TaggedManager and TaggedQuerySet with chainable tagged() methods implemented with django-tagging by fish2000 5 years ago
  5. (Modified/Improved) MultiQuerySet by joonas 6 years, 2 months ago

Comments

jsdalton (on July 19, 2010):

I have started using this pattern myself (I suggested the author upload it here) and can confirm its awesomeness.

I've seen many attempts at queryset chaining in Django, and they are invariably complex and frequently quite brittle. This approach is astoundingly simple and easy to use.

My only complaint is that there's a tad bit more excess boilerplate code to get it working than would be ideal. The purpose of the boilerplate is probably opaque to someone stumbling upon it and not knowing what it's for.

#

gsakkis (on July 20, 2010):

""" My only complaint is that there's a tad bit more excess boilerplate code to get it working than would be ideal. """

Check out #2117 for a no-boilerplate extension of the same idea.

#

Please login first before commenting.