Commits

Carl Meyer  committed 776726e

0.3.0

  • Participants
  • Parent commits 2cd3c13

Comments (0)

Files changed (6)

File CHANGELOG.txt

 django-model-utils changelog
 ============================
 
+v0.3.0
+------
+
+* Added ``QueryManager``
+
 
 Django model mixins and utilities.
 
-InheritanceCastModel
-====================
+models.InheritanceCastModel
+===========================
 
 This abstract base class can be inherited by the root (parent) model
 in a model-inheritance tree.  It allows each model in the tree to
     QuerySet subclass that could reduce this to k queries, where there
     are k subtypes in the inheritance tree.
 
-TimeStampedModel
-================
+models.TimeStampedModel
+=======================
 
 This abstract base class just provides self-updating ``created`` and
 ``modified`` fields on any model that inherits it.
+
+managers.QueryManager
+=====================
+
+Many custom model managers do nothing more than return a QuerySet that
+is filtered in some way. ``QueryManager`` allows you to express this
+pattern with a minimum of boilerplate::
+
+    from django.db import models
+    from model_utils.managers import QueryManager
+
+    class Post(models.Model):
+        ...
+        published = models.BooleanField()
+        pub_date = models.DateField()
+        ...
+
+        objects = models.Manager()
+        public = QueryManager(published=True).order_by('-pub_date')
+
+The kwargs passed to ``QueryManager`` will be passed as-is to the
+``QuerySet.filter()`` method. You can also pass a ``Q`` object to
+``QueryManager`` to express more complex conditions. Note that you can
+set the ordering of the ``QuerySet`` returned by the ``QueryManager``
+by chaining a call to ``.order_by()`` on the ``QueryManager`` (this is
+not required).

File model_utils/managers.py

+from django.db import models
+
+class QueryManager(models.Manager):
+    def __init__(self, *args, **kwargs):
+        if args:
+            self._q = args[0]
+        else:
+            self._q = models.Q(**kwargs)
+        super(QueryManager, self).__init__()
+
+    def order_by(self, *args):
+        self._order_by = args
+        return self
+
+    def get_query_set(self):
+        qs = super(QueryManager, self).get_query_set().filter(self._q)
+        if hasattr(self, '_order_by'):
+            return qs.order_by(*self._order_by)
+        return qs
+    

File model_utils/tests/models.py

 from django.db import models
 
 from model_utils.models import InheritanceCastModel, TimeStampedModel
+from model_utils.managers import QueryManager
+
 
 class InheritParent(InheritanceCastModel):
     pass
 
 class TimeStamp(TimeStampedModel):
     pass
+
+class Post(models.Model):
+    published = models.BooleanField()
+    confirmed = models.BooleanField()
+    order = models.IntegerField()
+
+    objects = models.Manager()
+    public = QueryManager(published=True)
+    public_confirmed = QueryManager(models.Q(published=True) &
+                                    models.Q(confirmed=True))
+    public_reversed = QueryManager(published=True).order_by('-order')
+
+    class Meta:
+        ordering = ('order',)

File model_utils/tests/tests.py

 from django.test import TestCase
 from django.contrib.contenttypes.models import ContentType
 
-from model_utils.tests.models import InheritParent, InheritChild, TimeStamp
+from model_utils.tests.models import InheritParent, InheritChild, TimeStamp, \
+    Post
 
 class InheritanceCastModelTests(TestCase):
     def setUp(self):
         t2 = TimeStamp.objects.create()
         t1.save()
         self.assert_(t2.modified < t1.modified)
+
+class QueryManagerTests(TestCase):
+    def setUp(self):
+        data = ((True, True, 0),
+                (True, False, 4),
+                (False, False, 2),
+                (False, True, 3),
+                (True, True, 1),
+                (True, False, 5))
+        for p, c, o in data:
+            Post.objects.create(published=p, confirmed=c, order=o)
+
+    def testPassingKwargs(self):
+        qs = Post.public.all()
+        self.assertEquals([p.order for p in qs], [0, 1, 4, 5])
+
+    def testPassingQ(self):
+        qs = Post.public_confirmed.all()
+        self.assertEquals([p.order for p in qs], [0, 1])
+
+    def testOrdering(self):
+        qs = Post.public_reversed.all()
+        self.assertEquals([p.order for p in qs], [5, 4, 1, 0])
  
 setup(
     name='django-model-utils',
-    version='0.2.1',
+    version='0.3.0',
     description='Django model mixins and utilities',
     long_description=open('README.txt').read(),
     author='Carl Meyer',