Login

QuerySetManager - easily add new QuerySet methods using a Model inner class

Author:
simon
Posted:
May 1, 2008
Language:
Python
Version:
.96
Score:
7 (after 9 ratings)

An easy way to add custom methods to the QuerySet used by a Django model. See simonwillison.net/2008/May/1/orm/ for an in-depth explanation.

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

class QuerySetManager(models.Manager):
    def get_query_set(self):
        return self.model.QuerySet(self.model)

# Using it in a model:

from django.db.models.query import QuerySet
import datetime

class Entry(models.Model):
   ...
   objects = QuerySetManager()
   ...
   class QuerySet(QuerySet):
        def on_date(self, date):
            next = date + datetime.timedelta(days = 1)
            return self.filter(
                posted__gt = date,
                posted__lt = next
            )

# Now you can get entries on a specific day like so:
#   Entry.objects.all().on_date(datetime.date.today())

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 5 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

dnordberg (on May 6, 2008):

This works for Entry.objects.filter().on_date(date) but not Entry.objects.on_date(date) as some may wish, for this add the following snippet to QuerySetManager.

`

def __getattr__(self, attr, *args):
    try:
        return getattr(self.__class__, attr, *args)
    except AttributeError:
        return getattr(self.get_query_set(), attr, *args)

`

#

exogen (on May 8, 2008):

In response to the above comment, I believe it can simple be written as:

def __getattr__(self, name):
    return getattr(self.get_query_set(), name)

...since the default attribute lookup will check self.class and superclasses.

#

zodiac2832 (on July 28, 2011):

I had to modify my manager to the following so I would not receive Pickle Errors.

# pickling causes recursion errors
_deny_methods = ['__getstate__', '__setstate__', '_db']

def __init__(self, queryset_cls=None):
    self._queryset_cls = queryset_cls
    super(PadManager, self).__init__()

def __getattr__(self, name):
    if name in self._deny_methods:
        raise AttributeError(name)
    return getattr(self.get_query_set(), name)

def get_query_set(self):
    return PadQuerySet(self.model)

#

Please login first before commenting.