Author: floguy
Date: Sun Sep 21 03:32:27 2008
New Revision: 30

Modified:
    trunk/things/__init__.py
    trunk/things/fields.py
    trunk/things/options.py

Log:
Added OrderCountField, which applies to either a ManyToManyField, or to a  
ForeignKey's RelatedManager, which does the required work to add an  
aggregate query and allow for ordering by that.

Modified: trunk/things/__init__.py
==============================================================================
--- trunk/things/__init__.py    (original)
+++ trunk/things/__init__.py    Sun Sep 21 03:32:27 2008
@@ -1,6 +1,6 @@
  from things.options import ModelThing, BaseThing
  from things.sites import ThingSite, site
-from things.fields import OrderField
+from things.fields import OrderField, OrderCountField

  def autodiscover():
      """

Modified: trunk/things/fields.py
==============================================================================
--- trunk/things/fields.py      (original)
+++ trunk/things/fields.py      Sun Sep 21 03:32:27 2008
@@ -1,5 +1,8 @@
  from django.template import defaultfilters
  from django.core.urlresolvers import reverse
+from django.db.models import ManyToManyField
+from django.db.models.options import FieldDoesNotExist
+from django.db import connection

  __all__ = ('OrderField', )

@@ -14,6 +17,7 @@
  class OrderField(BaseField):
      parent = None
      field_name = None
+    modifies_query_set = False

      def __init__(self, verbose_name_asc=None, verbose_name_desc=None,
                   url_asc=None, url_desc=None, field_url=None):
@@ -74,4 +78,46 @@
              self.parent.name_prefix, self.field_url),
              kwargs={
                  'url_prefix': self.parent.url_prefix,
-        })
\ No newline at end of file
+        })
+
+class OrderCountField(OrderField):
+    modifies_query_set = True
+
+    def _get_aggregate_name(self):
+        return '%s_count' % self.field_name
+    aggregate_name = property(_get_aggregate_name)
+
+    def modify_query_set(self, qs):
+        qn = connection.ops.quote_name
+        try:
+            parent_field = self.parent.opts.get_field(self.field_name)
+            m2m = True
+        except FieldDoesNotExist:
+            m2m = False
+        self_table = qn(self.parent.opts.db_table)
+        if m2m:
+            related_table = qn(parent_field.m2m_db_table())
+            related_column_name = qn(parent_field.m2m_column_name())
+        else:
+            # Need to instantiate the model, since we can't access  
RelatedManager
+            # instances unless it's through an instance instead of a class.
+            dummy_stupid = self.parent.model()
+            related_manager = getattr(dummy_stupid, self.field_name)
+            related_table = related_manager.model._meta.db_table
+            children = related_manager.all().query.where.children
+            related_column_name = None
+            for child in children:
+                if child[0] == related_table:
+                    related_column_name = child[1]
+                    break
+            if related_column_name is None:
+                raise ValueError("Could not determine relationship on  
related name %s" % self.field_name)
+            related_table = qn(related_table)
+            related_column_name = qn(related_column_name)
+
+        SQL = """
+        SELECT COUNT(*)
+        FROM %(related_table)s
+        WHERE %(related_table)s.%(related_column_name)s = %(self_table)s.id
+        """ % locals()
+        return qs.extra(select={self.aggregate_name: SQL})
\ No newline at end of file

Modified: trunk/things/options.py
==============================================================================
--- trunk/things/options.py     (original)
+++ trunk/things/options.py     Sun Sep 21 03:32:27 2008
@@ -7,7 +7,7 @@
  from django.template.loader import select_template
  from django.core.urlresolvers import reverse
  from django.db.models import Q
-from things.fields import BaseField
+from things.fields import BaseField, OrderCountField

  DETAIL_RE = re.compile('^(\d+)/$')

@@ -59,7 +59,10 @@
              pre = ''
              if descending == True:
                  pre = '-'
-            items = items.order_by('%s%s' % (pre, field.field_name))
+            if isinstance(field, OrderCountField):
+                items = items.order_by('%s%s' % (pre,  
field.aggregate_name))
+            else:
+                items = items.order_by('%s%s' % (pre, field.field_name))
          templates = ['%s/%s' % (self.template_dir, template_name,),
              '%s/list.html' % self.template_dir, 'things/list.html']
          t = select_template(templates)
@@ -129,13 +132,15 @@
          return patterns('', *tmp_urls)

      def get_query_set(self):
-        raise NotImplementedError
+        query_set = self.model._default_manager.all()
+        for field_name, field in self.fields.iteritems():
+            if field.modifies_query_set:
+                query_set = field.modify_query_set(query_set)
+        return query_set

  class ModelThing(BaseThing):
      def __init__(self, model):
          self.model = model
          self.opts = model._meta
          super(ModelThing, self).__init__()
-
-    def get_query_set(self):
-        return self.model._default_manager.all()
\ No newline at end of file
+
\ No newline at end of file

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pinax-updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pinax-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to